Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
522 commits
Select commit Hold shift + click to select a range
0e3834c
docs(prd610): record rejected cull trial and CPU scope evidence
jonit-dev Oct 14, 2026
46b27e5
docs(perf): record presentation profile and neutral vsync probe
jonit-dev Oct 14, 2026
8cbef6f
docs(perf): record incomplete physical display causal pair
jonit-dev Oct 14, 2026
d2ac7df
docs(perf): re-plan PRD-610 on a matched yardstick and structural levers
jonit-dev Oct 14, 2026
0f98d49
fix(midway): require matched production builds before benchmarking
jonit-dev Oct 14, 2026
a4c99a3
fix(midway): pack Three through its exported entry
jonit-dev Oct 14, 2026
4e3879a
fix(midway): verify production acquisition and restore dashboard typing
jonit-dev Oct 14, 2026
5950547
test(three-native): align stale GC assertions with bounded settled sweep
jonit-dev Oct 14, 2026
8b1d80d
fix(midway): collect matched driven thread CPU windows for dashboard …
jonit-dev Oct 14, 2026
db5a72c
fix(playtest): narrow validated window ticks for declaration generation
jonit-dev Oct 14, 2026
050e479
fix(midway): contain dashboard metric table overflow
jonit-dev Oct 14, 2026
580929c
fix(playtest): identify Chromium renderer leader for CPU windows
jonit-dev Oct 15, 2026
14c5643
fix(midway): stop stacking cold dashboard polls and show a loading state
jonit-dev Oct 15, 2026
d790e5c
fix(native): hold automatic renders inside matched CPU windows
jonit-dev Oct 15, 2026
365d00f
feat(midway): calibrate CPU profiles to one monotonic clock
jonit-dev Oct 15, 2026
db22a62
fix(midway): show provisional legacy CPU rows and native failures
jonit-dev Oct 15, 2026
e3271a1
fix(midway): reconcile native CPU windows in host ticks
jonit-dev Oct 15, 2026
fef738f
docs(prd-610): record the matched baseline and the IPC re-plan
jonit-dev Oct 15, 2026
b555246
docs(PRD-612): file the web Wasm vs three.js target
jonit-dev Oct 15, 2026
452e7eb
feat(midway): lead the dashboard with matched native and web Wasm res…
jonit-dev Oct 15, 2026
e41c0c1
feat(midway): track iteration cycles against a 30 minute goal
jonit-dev Oct 15, 2026
13498c5
docs(PRD-613): file the native render thread under the native-engine …
jonit-dev Oct 15, 2026
900b106
docs(PRD-613): stage the render thread plan
jonit-dev Oct 15, 2026
4abe3d0
perf(PRD-613): stage 0 render phase split diagnostic
jonit-dev Oct 15, 2026
39c8a70
fix(midway): dashboard KPI card crashed on a missing baseline
jonit-dev Oct 15, 2026
1ae4abd
docs(PRD-612): web Wasm owner profile shares
jonit-dev Oct 15, 2026
d28c69c
docs(PRD-610): record two rejected levers
jonit-dev Oct 15, 2026
26a0348
docs: PERFORMANCE-LEARNINGS.md, the central perf lever record
jonit-dev Oct 15, 2026
a574238
wip(PRD-613): stage 1 render thread behind TN_RENDER_THREAD (default …
jonit-dev Oct 15, 2026
f9f8422
docs: learnings file avoids redundancy, insights only when valuable
jonit-dev Oct 15, 2026
5b17462
docs(PRD-613): record inconclusive matched render-thread screen
jonit-dev Oct 15, 2026
539151b
feat(playtest): sample native stacks inside exact CPU windows
jonit-dev Oct 15, 2026
b9f8c7f
docs(perf): reject narrow web glue lever and record steady native owners
jonit-dev Oct 15, 2026
7d1fd69
fix(perf): show recent exact-window measurements above stale headlines
jonit-dev Oct 15, 2026
e91afa6
wip(perf): allow isolated ABI-matched compressed V8 prototype
jonit-dev Oct 15, 2026
7ebc6cc
docs(perf): reject compressed V8 candidate after all-pose regression
jonit-dev Oct 15, 2026
7b9949f
docs(perf): distinguish capture timeout from visibility trial results
jonit-dev Oct 15, 2026
d838444
perf(native): measure material invalidation at exact hold boundaries
jonit-dev Oct 15, 2026
99db31e
docs(perf): reject redundant opacity invalidation guard budget
jonit-dev Oct 15, 2026
18839e5
fix(native): preserve embedded scripts and SDL tray under IPO
jonit-dev Oct 15, 2026
91984c8
docs: close GCC IPO screen as CPU inconclusive
jonit-dev Oct 15, 2026
1766f64
perf(native): prototype bitwise Object3D compose reuse
jonit-dev Oct 15, 2026
09a05e0
docs: reject compose cache performance candidate
jonit-dev Oct 15, 2026
5fdbed5
perf(native): restore original Object3D after compose trial
jonit-dev Oct 15, 2026
b291845
test(native): preserve scalar setter construction after fast-call trial
jonit-dev Oct 15, 2026
1516cbc
feat(core): retain successful render completion cadence
jonit-dev Oct 15, 2026
2c430db
feat(playtest): observe native application presentation cadence
jonit-dev Oct 15, 2026
b74c622
Add private browser playtest clock transitions
jonit-dev Oct 15, 2026
b31f284
Show exploratory application completion windows
jonit-dev Oct 15, 2026
4199bb6
feat(playtest): collect application completion cadence windows
jonit-dev Oct 15, 2026
24a3d10
docs(perf): record unqualified completion diagnostic
jonit-dev Oct 15, 2026
7aa1187
docs(perf): record native completion coarse discriminator
jonit-dev Oct 15, 2026
703f7af
perf(playtest): sample owned native process in diagnostic windows
jonit-dev Oct 15, 2026
6ccd0c1
docs(perf): record native presentation worker ownership
jonit-dev Oct 15, 2026
47b4d8f
docs(perf): record unqualified Wasm completion diagnostic
jonit-dev Oct 15, 2026
49b39a3
perf(native): expose opt-in resolved GPU timing diagnostics
jonit-dev Oct 15, 2026
55c21d8
docs(perf): record parked GPU-timer admission
jonit-dev Oct 15, 2026
4bc99e2
fix(playtest): bind completion windows to negotiated epoch
jonit-dev Oct 15, 2026
8a51dec
docs(perf): reject flat quaternion direct-buffer trial
jonit-dev Oct 15, 2026
c06fa88
docs(perf): bound dirty-subtree prerequisite design
jonit-dev Oct 15, 2026
9008d44
docs(perf): reject mismatched Wasm symbol provenance
jonit-dev Oct 15, 2026
273f117
docs(perf): record unchanged-link symbol recovery limit
jonit-dev Oct 15, 2026
f92d01c
docs(perf): clarify paired ratio aggregation
jonit-dev Oct 15, 2026
6878c53
perf(native): the player's game thread owns one physical core (PRD-61…
jonit-dev Oct 15, 2026
61c7c1d
perf(native): auto placement takes the last-ranked core (PRD-610 AC-20)
jonit-dev Oct 15, 2026
c4be636
perf(native): placement splits by L3 domain, P-cores first (PRD-610 A…
jonit-dev Oct 15, 2026
527cb8f
docs(perf): record placement lesson and two closed levers (PRD-610)
jonit-dev Oct 15, 2026
fa56efb
Merge perf/prd610-resume into PRD-573 epic
jonit-dev Oct 15, 2026
20adb41
Merge origin/develop into PRD-573 epic
jonit-dev Oct 15, 2026
69c2b41
perf(core): serialize a changed HUD frame once, not three times
jonit-dev Oct 15, 2026
d92b63a
revert(native): drop the TN_JS_MATH_BULK_READ experiment
jonit-dev Oct 15, 2026
c497fa9
feat(config): the native engine is the default; engine: "legacy" is t…
jonit-dev Oct 15, 2026
eea2dd0
test(scaffold): pin the legacy engine in the recast bundle check and …
jonit-dev Oct 15, 2026
18eae9f
test(core): type the stringify spy call in the HUD serialize test
jonit-dev Oct 15, 2026
0a3cb14
style: biome format and one useTemplate lint error in midway-cycles.spec
jonit-dev Oct 15, 2026
aa828a9
feat(templates): pin the seven templates the native engine cannot bin…
jonit-dev Oct 15, 2026
72b606b
perf(native): thread placement is opt-in until a policy passes (PRD-6…
jonit-dev Oct 15, 2026
604080c
test(scaffold): recompute the tree hashes of the seven pinned templates
jonit-dev Oct 15, 2026
cc1f2ef
docs(perf): record the L3-domain placement reject (PRD-610)
jonit-dev Oct 15, 2026
0adff67
fix(runtime-native): the V8 player takes the runner's window flags an…
jonit-dev Oct 15, 2026
8ff89e9
feat(create-threenative): pin four templates the native engine cannot…
jonit-dev Oct 15, 2026
4a78381
docs(verification): regenerate the native coverage record after the e…
jonit-dev Oct 15, 2026
96910fd
feat(create-threenative): pin minimal and puzzle too, fold the Engine…
jonit-dev Oct 15, 2026
450650f
test(runtime-native): let the downloader provision cgltf for the engi…
jonit-dev Oct 15, 2026
4816de0
docs(prd): record the v1 release decisions, the native default and it…
jonit-dev Oct 15, 2026
e060286
Merge branch 'perf/prd610-resume' into docs/unreal-class-epic
jonit-dev Oct 15, 2026
846816d
chore(deps): point the lockfile at develop's three@0.185.1 patch hash
jonit-dev Oct 15, 2026
1cbf2e4
docs(perf): close the thread placement lever, opt-in for v1 (PRD-610 …
jonit-dev Oct 15, 2026
21ddd87
test: bring the specs the perf lane and develop left red back in line…
jonit-dev Oct 15, 2026
09b1def
feat(examples): pin abyss-framework to the legacy engine
jonit-dev Oct 15, 2026
d42ddd8
Merge branch 'perf/prd610-resume' into docs/unreal-class-epic
jonit-dev Oct 15, 2026
12f0096
docs(verification): regenerate the native coverage record after the P…
jonit-dev Oct 15, 2026
35f352f
wip(PRD-617): starter post and TSL bindings, round 1 (uncompiled)
jonit-dev Oct 15, 2026
202e04e
wip(PRD-617): starter post and TSL bindings, round 2
jonit-dev Oct 15, 2026
b37921b
fix(native): bind the members four templates need and fail runs on V8…
jonit-dev Oct 15, 2026
5519da7
wip(PRD-617): starter post bindings round 3 — zero V8 refused imports
jonit-dev Oct 15, 2026
0d847fd
wip(PRD-617): round 4 — TRAA lifecycle and rtt quad/manual update
jonit-dev Oct 15, 2026
d599bb4
fix(runtime-native): ship the native-engine desktop bundler in the pu…
jonit-dev Oct 15, 2026
879511f
fix(runtime-native): installed games get the engine player and bundle…
jonit-dev Oct 15, 2026
f4843f3
ci(release): the clean consumer builds a packed native-engine game be…
jonit-dev Oct 15, 2026
8c105da
fix(native): keep the output and blit passes on their own scene colou…
jonit-dev Oct 15, 2026
75f2485
fix(web-engine): route the refused display addons and share the TSL e…
jonit-dev Oct 15, 2026
15ca224
fix(runtime-native): ship the native-engine desktop bundler in the pu…
jonit-dev Oct 15, 2026
5c1c3d9
fix(runtime-native): the shipped engine player links the physics ABI
jonit-dev Oct 15, 2026
690073c
fix(native): BufferGeometry.setIndex(null) removes the index
jonit-dev Oct 15, 2026
7c402fd
fix(runtime-native): only the three package counts as upstream in the…
jonit-dev Oct 15, 2026
68dd0a8
fix(native): Fn with parameters builds per call, and the player repor…
jonit-dev Oct 15, 2026
806890c
fix(core): replay reads the canvas rectangle only when the host canva…
jonit-dev Oct 15, 2026
02413c4
fix(web-engine): vec4(normalView, 0) names the normal target on the W…
jonit-dev Oct 15, 2026
a35652d
docs(prd): file PRD-620, the native engine runs TSL compute
jonit-dev Oct 15, 2026
521c8ea
docs(prd): PRD-620 phases carry their own boxes
jonit-dev Oct 15, 2026
6e7a329
fix(native): Texture.dispose exists on the native engine (PRD-617)
jonit-dev Oct 15, 2026
b7de6ee
fix(web-engine): bind BlendMode and three's number-only MathUtils on …
jonit-dev Oct 15, 2026
73dec46
fix(create-threenative): the web build of a native-engine game cooks …
jonit-dev Oct 15, 2026
4612e3d
fix(build): the web build for the native engine cooks models without …
jonit-dev Oct 15, 2026
293556f
fix(native): a Mesh takes a material array and draws one group per ma…
jonit-dev Oct 15, 2026
9ed3f15
feat(native): the native engine runs TSL compute on V8 and Wasm (PRD-…
jonit-dev Oct 15, 2026
0f643c6
feat(templates): puzzle runs on the native engine, legacy pin removed…
jonit-dev Oct 15, 2026
38770ef
feat(runtime-native): TSL operators SoftBody3D compute needs (PRD-620)
jonit-dev Oct 15, 2026
54850e0
Merge prd617/runtime-fixes into prd617/integration
jonit-dev Oct 15, 2026
f86f01d
fix(renderer): the normal and velocity passes add nothing to the fram…
jonit-dev Oct 15, 2026
d4f791f
Merge prd617/post-bindings into prd617/integration
jonit-dev Oct 15, 2026
709c778
test(runtime-native): drop the unused ts-expect-error on the bundler …
jonit-dev Oct 15, 2026
a7db4f9
fix(abi): localToWorld and worldToLocal answer the vector they converted
jonit-dev Oct 15, 2026
49fef5b
feat(material): bind Material.colorWrite
jonit-dev Oct 15, 2026
37ed3ba
fix(three-native): BufferAttribute.updateRanges is a live array on th…
jonit-dev Oct 15, 2026
0eb8453
fix(native): a zero-parameter Fn builds per call on V8, as on Wasm an…
jonit-dev Oct 15, 2026
390c657
test(runtime-native): packed consumer installs resolve the cohort fro…
jonit-dev Oct 15, 2026
f77b1fe
fix(abi): Object3D.raycast exists on both back ends
jonit-dev Oct 15, 2026
25b98c6
test(abi): catalog_coverage allows the adapter's Object3D.raycast
jonit-dev Oct 15, 2026
43ff539
feat(native): bind DecalGeometry, setFromPoints and the examples/jsm …
jonit-dev Oct 15, 2026
64911ac
fix(native): a model's shared images ship in the native package and l…
jonit-dev Oct 15, 2026
fae99b4
fix(web-host): TN_POST_NORMAL_SKIPPED is a console log, not a console…
jonit-dev Oct 16, 2026
6d736a4
Merge prd617/runtime-fixes (37ed3ba4d) into prd617/integration
jonit-dev Oct 16, 2026
d2994b0
Merge branch 'prd617/post-bindings' into prd617/integration
jonit-dev Oct 16, 2026
4215b29
Merge branch 'prd617/runtime-fixes' into prd617/integration
jonit-dev Oct 16, 2026
1e8898d
chore(three-native): resync the native registry snapshot after the me…
jonit-dev Oct 16, 2026
4426e16
Revert "feat(examples): pin abyss-framework to the legacy engine"
jonit-dev Oct 16, 2026
144b972
fix(native): localToWorld answers its vector, and bind computeFrenetF…
jonit-dev Oct 16, 2026
95f4373
Merge remote-tracking branch 'origin/develop' into prd617/integration
jonit-dev Oct 16, 2026
9598fe2
docs(prd): file PRD-617, every template runs on the native engine
jonit-dev Oct 15, 2026
888ecd6
docs(prd): PRD-617 covers the eleven pinned templates
jonit-dev Oct 15, 2026
9abc4f1
docs(prd): PRD-617 blocks v1, native default stays (owner decision)
jonit-dev Oct 15, 2026
82154b5
chore: repair the lockfile after merging origin/develop
jonit-dev Oct 16, 2026
1c57737
docs(prd): PRD-573 records the owner decision, native stays the defau…
jonit-dev Oct 16, 2026
897fd24
chore: clear the lint errors and the typecheck error the branch merge…
jonit-dev Oct 16, 2026
55c32d1
chore(scripts): verify-one-template-desktop names the packed files in…
jonit-dev Oct 16, 2026
f7503f6
docs(verification): regenerate the native coverage record after the i…
jonit-dev Oct 16, 2026
c846430
fix(native): a playtest bridge call that answers undefined reaches th…
jonit-dev Oct 16, 2026
bfcdeac
chore(three-native): waive the new suppressions with reasons
jonit-dev Oct 16, 2026
e1ce0f9
fix(scripts): the golden path scaffold overrides the transitive cohor…
jonit-dev Oct 16, 2026
2170a03
fix(native): a playtest pointer or wheel the UI does not take reaches…
jonit-dev Oct 16, 2026
b4a4708
test(runtime-native): the iOS packaging check allows the engine playe…
jonit-dev Oct 16, 2026
854d44e
test(create-threenative): puzzle leaves the legacy-pin list and its t…
jonit-dev Oct 16, 2026
6aa48de
feat(three-native): toAttribute, ReadbackBuffer on Wasm, storage arra…
jonit-dev Oct 16, 2026
2688513
chore(three-native): publint gate, README row, source-only externals …
jonit-dev Oct 16, 2026
61a37fa
fix(release): the publish check knows the engine bundler resolves pla…
jonit-dev Oct 16, 2026
0c6247f
chore(examples): abyss-framework keeps a named temporary legacy pin w…
jonit-dev Oct 16, 2026
b7decc3
fix(playtest): the held applySetup hands back its confirmation, and t…
jonit-dev Oct 16, 2026
0d1a8b2
feat(templates): minimal and platformer run on the native engine
jonit-dev Oct 16, 2026
9d5ad56
merge prd617/integration into post-bindings
jonit-dev Oct 16, 2026
db06c71
test(scaffold): recompute the minimal and platformer tree hashes with…
jonit-dev Oct 16, 2026
80cf4c2
test(runtime-native): the V8 player pins BlendMode and the number-onl…
jonit-dev Oct 16, 2026
58bbab0
feat(runtime-native): Return, Break, Continue, log and deltaTime in T…
jonit-dev Oct 16, 2026
c37beda
Merge origin/develop into prd617/develop-merge
jonit-dev Oct 16, 2026
49f85f1
feat(runtime-native): what snow's GPUParticles3D needs from TSL and S…
jonit-dev Oct 16, 2026
b5753a9
WIP recovery(PR493): preserve unverified integration and Wasm packagi…
jonit-dev Oct 16, 2026
720ea50
WIP recovery(PR493): preserve unverified runtime and template decoder…
jonit-dev Oct 16, 2026
8d27e2c
WIP recovery(PR493): preserve unverified post-binding and template edits
jonit-dev Oct 16, 2026
071f82c
Merge branch 'prd617/post-bindings' into prd617/develop-merge
jonit-dev Oct 16, 2026
e4138f9
Merge recovered PR493 runtime work preserving decoder and wheel fixes
jonit-dev Oct 16, 2026
bd62964
Merge branch 'prd617/integration' into prd617/develop-merge
jonit-dev Oct 16, 2026
b4df9b3
fix(recovery): retain committed pointer and wheel behavior over super…
jonit-dev Oct 16, 2026
687729c
chore(recovery): refresh measured scaffold hashes and PRD617 status
jonit-dev Oct 16, 2026
470290a
chore(native): sync recovered Curve declaration and build checks
jonit-dev Oct 16, 2026
a221bfc
fix(three-native): identify browser node materials for cloth consumers
jonit-dev Oct 16, 2026
eae462f
fix(native): carry storage attributes and indices into fragments
jonit-dev Oct 16, 2026
5d67345
test(core): resolve native cloth catalog independently of working dir…
jonit-dev Oct 16, 2026
6bb4fba
fix(native): preserve typed uniform values through GPU uploads
jonit-dev Oct 16, 2026
7a63a92
fix(three-native): refresh reflected bounds and sprite node metadata
jonit-dev Oct 16, 2026
084f6ca
fix(native): preserve playtest pointer button transitions
jonit-dev Oct 16, 2026
1f3e679
fix(native): reuse storage bindings across graph lowering
jonit-dev Oct 16, 2026
118f2b2
test(native): retain traced UI overlay artifacts
jonit-dev Oct 16, 2026
ac57da7
fix(native): preserve camera conventions and buffer disposal lifetimes
jonit-dev Oct 16, 2026
944dc67
fix(native): retire disposed storage bindings safely
jonit-dev Oct 16, 2026
99e88c2
fix(web): preserve native attribute array edits by range
jonit-dev Oct 16, 2026
b584297
test(wasm): exercise per-call Fn graphs and scopes
jonit-dev Oct 16, 2026
048cb74
fix(coverage): include owned native engine qualification
jonit-dev Oct 16, 2026
36ded50
docs(prd617): record remaining starter and snow passes
jonit-dev Oct 16, 2026
947ad23
fix(coverage): distinguish binary inspections from executions
jonit-dev Oct 16, 2026
9e07f53
docs(coverage): refresh Linux legacy and owned engine proof
jonit-dev Oct 16, 2026
13b7733
perf(core): batch plain heightfield attribute writes
jonit-dev Oct 16, 2026
244e4d1
test: align recovered template contracts and record Snow validation
jonit-dev Oct 16, 2026
2392849
fix: measure streaming host turns through the yield seam
jonit-dev Oct 16, 2026
f2c4bf6
perf: test bounded Heightfield upload ranges
jonit-dev Oct 16, 2026
28eb709
revert: reject Heightfield ranges after paired tail regressions
jonit-dev Oct 16, 2026
371148c
fix: base starter quality fallback on completed work
jonit-dev Oct 16, 2026
a99e3f7
test: record starter quality source fingerprint
jonit-dev Oct 16, 2026
50d1592
fix(playtest): retain primary failure during cleanup
jonit-dev Oct 16, 2026
09359fc
fix(wasm): report completed GPU timing with source frames
jonit-dev Oct 16, 2026
113a734
docs: preserve native template recovery and Snow experiment results
jonit-dev Oct 16, 2026
c8a7b26
Fix deterministic native captures without advancing simulation
jonit-dev Oct 16, 2026
d6d04b9
fix(native): decode data: URLs in fetch and share the mystral link po…
jonit-dev Oct 16, 2026
08a63c4
fix(native): install a host Image so stock three.js SMAA loads its lo…
jonit-dev Oct 16, 2026
cd1ff45
docs(prd): PRD-617 records the native Image shim and stock-three SMAA…
jonit-dev Oct 16, 2026
8cec8d8
fix(native): split the Image load-token assignment for lint
jonit-dev Oct 16, 2026
af24f65
feat(playtest): perf --executable reports on-CPU time per frame
jonit-dev Oct 16, 2026
badba06
perf(core): heightfield refresh uploads only the rows it touched
jonit-dev Oct 16, 2026
bb5a77f
feat(native): offscreen PassNode on a separate scene, drawn where the…
jonit-dev Oct 16, 2026
c198e66
fix(templates): split starter quality policy under the render-file ca…
jonit-dev Oct 16, 2026
f34bd6a
fix(core): a missing WebGPU adapter fails boot with a readable TN_NO_…
jonit-dev Oct 16, 2026
3e65d6a
perf(playtest): report the busiest thread; PRD-617 AC-4 starter CPU
jonit-dev Oct 16, 2026
ad3d211
fix(three-native): web Wasm engine boots shooter, sailing, runner and…
jonit-dev Oct 16, 2026
8aefa64
docs(prd): PRD-617 AC-2 and AC-3 pass for the starter on desktop and web
jonit-dev Oct 16, 2026
21c984f
docs(prd): PRD-617 names the exact build behind the starter desktop e…
jonit-dev Oct 16, 2026
088d138
docs(prd): PRD-617 AC-1, the starter carries no legacy pin and bundle…
jonit-dev Oct 16, 2026
751cbc4
fix(three-native): the Wasm engine glTF loader hosts TN_discrete_lod
jonit-dev Oct 16, 2026
3ebec61
fix(core): LOD selection no longer calls Sphere.clone, which the engi…
jonit-dev Oct 16, 2026
4a707a8
fix(native): a post texture that moves no longer frees the bind group…
jonit-dev Oct 17, 2026
8079d37
fix(native): bounds of a skinned mesh read before the first frame can…
jonit-dev Oct 17, 2026
41e19a5
fix(native): a Fn result that ran statements lowers its statements on…
jonit-dev Oct 17, 2026
f73ccfe
fix(native): a material node that reads a post render-to-texture pass…
jonit-dev Oct 17, 2026
878de50
fix(native): screenSize reaches the vertex uniform block
jonit-dev Oct 17, 2026
796ee3e
fix(native): put the renderer.cpp bind-group hunks where they were wr…
jonit-dev Oct 17, 2026
f3eba20
feat(native): NodeMaterial.depthNode writes the fragment's depth
jonit-dev Oct 17, 2026
ff25677
fix(native): NodeMaterial.depthNode writes frag_depth on every mesh m…
jonit-dev Oct 17, 2026
04e74dc
perf(native): read the post-views stamp once per renderPrepared call
jonit-dev Oct 17, 2026
fc3de35
docs(prd): PRD-617 AC-6 evidence, rain parity on the Wasm engine
jonit-dev Oct 17, 2026
8316541
fix(wasm-host): stop drawing while two frames are still on the GPU, s…
jonit-dev Oct 17, 2026
58bd532
feat(create-threenative): rain runs on the native engine; its legacy …
jonit-dev Oct 17, 2026
9730115
test(create-threenative): rain's scaffold hash follows its deleted le…
jonit-dev Oct 17, 2026
54c2268
fix(native): TSL mat2 with four plain numbers is row-major, as three'…
jonit-dev Oct 17, 2026
7ec1bf0
docs(skills): add tempest-performance-loop
jonit-dev Oct 17, 2026
0b8f9a9
docs(skills): fold the Tempest campaign into native-performance-loop
jonit-dev Oct 17, 2026
1d9c193
test: follow the named TN_NO_RENDERER boot failure; waive the TSL Loo…
jonit-dev Oct 17, 2026
b7362aa
perf(runtime-native): a material's slots lower their shared nodes once
jonit-dev Oct 17, 2026
9c655bf
feat(runtime-native): the starter's LUT colour grade lowers on native
jonit-dev Oct 17, 2026
eb42aa7
fix(three-native): keep a uniform's update hook alive after the game …
jonit-dev Oct 17, 2026
7864ee1
fix(native): read a light target's matrixWorld as three does, never r…
jonit-dev Oct 17, 2026
044b979
fix(three-native): pass the rendering camera and scene to uniform upd…
jonit-dev Oct 17, 2026
f3d200a
feat(native): apply scene.fogNode, so the Wasm engine fogs as stock t…
jonit-dev Oct 17, 2026
3ada9cb
fix(runtime-native): continuous VSM invalidation rotates the level gr…
jonit-dev Oct 17, 2026
9da4048
fix(runtime-native): retain VSM casters beyond the source shadow camera
jonit-dev Oct 17, 2026
27beb34
fix(runtime-native): the V8 player's TSL extras receive vec4, so fog(…
jonit-dev Oct 17, 2026
aa0e6c1
fix(native): route scene fog nodes through the V8 shader bridge
jonit-dev Oct 17, 2026
b1ecdb5
fix(native): bridge NodeMaterial shader slots and material arguments
jonit-dev Oct 17, 2026
cd98f1d
ci(runtime-native): the shipped web Wasm engine has a 4 MiB size ceiling
jonit-dev Oct 17, 2026
fde750f
fix(racing): add the sun's target to the scene so the sun aims at the…
jonit-dev Oct 17, 2026
b1ec75b
fix(runtime-native): frame GPU time sums every pass, offscreen passes…
jonit-dev Oct 17, 2026
e894154
fix(three-native): registry snapshot names the Scene.fogNode getter
jonit-dev Oct 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
11 changes: 10 additions & 1 deletion .agents/skills/native-performance-loop/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: native-performance-loop
description: Run an autonomous ThreeNative native-performance optimization loop using existing harnesses, quick synthetic load tests, and representative real games. Profile bottlenecks, make focused changes, accept or reject measured experiments, and maintain an HTML benchmark dashboard. Use for sustained native runtime optimization, frame pacing, startup, memory, or thermal efficiency campaigns.
description: Run an autonomous ThreeNative native-performance optimization loop using existing harnesses, quick synthetic load tests, and representative real games. Profile bottlenecks, make focused changes, accept or reject measured experiments, and maintain an HTML benchmark dashboard. Use for sustained native runtime optimization, frame pacing, startup, memory, or thermal efficiency campaigns, including the Tempest (rain) campaign where the web Wasm engine must beat stock three.js with the same image.
---

# Native performance loop
Expand Down Expand Up @@ -41,6 +41,15 @@ the developer to supervise each iteration. Creating or editing this skill does n
Keep separate goals for frame tails, startup, memory, and energy. Never optimize a blended
score that can conceal one game's regression. Run the unchanged baseline before editing.

## KPIs and named campaigns

- Score every campaign on [engine-kpis.md](references/engine-kpis.md) as well as on its primary
scalar. Keep a lever only if it moves at least one engine KPI and the sentinel game does not
regress. A lever that helps one game only is `provisional`.
- For the Tempest sample (the `rain` template, web Wasm engine against stock three), read
[tempest.md](references/tempest.md). It sets goals T1 to T3, the image-identity rule, the arms,
the capture recipe and the known state.

## The experiment loop

Repeat without asking for a new task after each result:
Expand Down
2 changes: 1 addition & 1 deletion .agents/skills/native-performance-loop/agents/openai.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
interface:
display_name: "Native Performance Loop"
short_description: "Optimize native games with measured keep/reject loops"
short_description: "Optimize native games and Tempest with measured keep/reject loops"
default_prompt: "Use $native-performance-loop to improve native game performance, choose representative workloads, keep verified gains, and maintain an HTML benchmark dashboard."
61 changes: 61 additions & 0 deletions .agents/skills/native-performance-loop/references/engine-kpis.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Engine KPIs that pay in every game

These KPIs are the scoreboard of every campaign, whatever its workload. Each one measures an
engine cost that every game pays when it draws. A lever that moves one of them helps all
templates. A lever that moves only one game's frame time is suspect.

Record each KPI for both arms (the engine under test and its control, such as stock three on the
web or the incumbent build) at the frozen pose or route. Where a meter is
missing, add the smallest meter with a check as a separate harness change, then re-baseline. Do
not estimate a value.

## GPU (rank first when the game is GPU-bound)

| KPI | Definition | Target | Meter |
| --- | --- | --- | --- |
| G1 GPU cost ratio | Engine GPU ms ÷ control GPU ms (stock three on the web), same pose, size and tier | ≤ 1.0, then lower | playtest `assert.performance` window `gpuMs`, both arms |
| G2 Shader cost per material | Instructions, texture samples and loop trip counts in the emitted WGSL, against three's WGSL for the same node graph | ≤ three on every program | WGSL dump from both engines; diff per program |
| G3 Full-screen passes per frame | Passes that touch every pixel, plus MSAA resolves and target-to-target copies | ≤ three; 0 redundant copies | pass list from the render graph; Dawn capture if needed |
| G4 Render-target bytes | Sum of live color, depth and MSAA target memory | ≤ three | renderer target census |
| G5 Load/store waste | Clears and stores of targets that the next pass overwrites or never reads | 0 | pass descriptors (loadOp/storeOp) |

## CPU and the JS/Wasm boundary

| KPI | Definition | Target | Meter |
| --- | --- | --- | --- |
| C1 Render CPU ms | CPU time from `render()` entry to submit | ≤ three | window `cpuMs` |
| C2 Boundary calls per frame | JS→Wasm and Wasm→JS calls in one steady frame | falls as levers land | call counter in `packages/three-native` glue |
| C3 Steady GPU object churn | Bind groups, buffers, textures and pipelines created per steady frame | 0 | create counters in the renderer |
| C4 Upload bytes per frame | `writeBuffer`/`writeTexture` bytes in a steady frame | only data that changed | upload counter |

## Startup and hitches

| KPI | Definition | Target | Meter |
| --- | --- | --- | --- |
| S1 Pipeline count and compile time | Distinct render pipelines at the pose, and `compileMs` / `compileSettledMs` | ≤ three | `pipelineCensus`, compile fields |
| S2 First-use hitch | Worst frame in the first 5 s after the pose is ready | ≤ 2x budget | presented intervals after the ready mark |
| S3 Time to first frame | Navigation start to the first presented world frame | ≤ three | loading scenario marks |

## Pacing and memory

| KPI | Definition | Target | Meter |
| --- | --- | --- | --- |
| P1 Presented interval | p50, p95 and p99 of the real presented interval (not rAF and not fps) | p95 ≤ budget | presentation samples |
| P2 Frames in flight | Frames submitted and not yet complete | ≤ 2 (backpressure) | `framesOnGpu` in `web_host.cpp` |
| M1 Steady memory growth | JS heap and Wasm memory growth per minute at the pose | 0 after warmup | `performance.memory`, `WebAssembly.Memory` byte length |

## Guard KPIs (must not move)

| KPI | Definition | Limit |
| --- | --- | --- |
| V1 Visual parity | Mean absolute diff against the control at the pose, 0–255 | ≤ 0.01 and judge NEUTRAL or IMPROVEMENT |
| V2 Behavior | The workload's playtest set and the sentinel game's set | No new red |
| V3 Workload identity | Draw calls, triangles and active stages | Same as the baseline, unless the lever deletes provably redundant work and the judge passes |

## Reading the scoreboard

- Report each KPI as baseline, incumbent and absolute delta, with a percent only for a positive
baseline. Do not blend KPIs into one score.
- Show a KPI that is not yet metered as `unavailable: <reason>`.
- A drop in G3, G5, C3 or C4 with no GPU or CPU ms change is still a kept maintenance win only if
it is proven on the sentinel. Label it as such. Do not label it a speedup.
167 changes: 167 additions & 0 deletions .agents/skills/native-performance-loop/references/tempest.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
# Tempest campaign

Read this file when the campaign workload is the Tempest sample: the `rain` template
(`packages/create-threenative/templates/rain`), drawn by the web Wasm engine against stock three.js.
Tempest is per-pixel heavy (a raymarched sky and clouds, a reflection pass, 4x MSAA, bloom and a
grade). It is the worst case for engine render cost, so a lever that pays here pays in every game
that draws full-screen passes, materials or render targets.

The skill's loop, acceptance rules and dashboard contract apply. This file adds only what differs.
The web lane is the primary lane here. That is an exception to the skill's native-first rule: the
Wasm engine is the engine under test on the web, and T3 carries the result to the native player.

## Contract

1. **Goal order.**
- **T1:** Wasm engine GPU ms is at or below stock three on the same pose, resolution and tier.
- **T2:** 60 fps on the reference GPU. GPU ms ≤ 16.7 and presented interval p95 ≤ 16.7 ms
at 1920x1080, `high` tier.
- **T3:** the same on the native desktop V8 player.

T1 comes first because it is an owner rule: native must beat JS.
2. **Primary scalar.** GPU ms per frame, median of steady windows, lower is better. Do not
use `fps` or `minFps` from the Wasm engine as the primary scalar. The rAF backpressure
(`tnw_web_frame(11)`, two frames on the GPU) skips renders, so both values overstate the engine.
Read CPU ms, GPU ms and the presented interval.
3. **Allowed edit surface.**
- Engine only: `packages/runtime-native/` (C++, WGSL codegen, the renderer, `web_host.cpp`) and
`packages/three-native/` (JS glue).
- The template's `src/render/` and `tools/tempest-*.frag` are the look. Do not change them
for speed. A template-side saving (cloud steps, reflection resolution, MSAA, bloom resolution)
is a measured *proposal* for the owner. It is not a kept lever.
- Do not patch three.js.
4. **Image identity.** The Wasm frame must match stock three on the pose (mean absolute diff
≤ 0.01 on 0–255, plus no region the judge marks as different). Every kept lever passes a fresh
read-only visual judge with BEFORE/AFTER captures and two runs per arm. Both engines are
deterministic run to run, so two runs show stability, not two independent samples.
5. **Generality gate.** A lever is kept only if it moves at least one KPI in
[engine-kpis.md](engine-kpis.md) and does not regress a second template (the sentinel). Use
`starter`, or a template whose bottleneck differs from Tempest. A lever that only helps
Tempest's shaders is `provisional`, never `keep`.

## Start or resume

1. Do the "Start or resume" steps of the skill. Use the campaign directory
`<primary>/artifacts/native-performance-loop/tempest-<date>/`. Copy `render.mjs` and
`check-render.mjs` from the newest campaign there instead of writing a renderer. Create
`index.html` before the first run.
2. Read the arms and lanes sections below for the arms, the capture recipe and the frozen pose.
Then read [engine-kpis.md](engine-kpis.md) and record a baseline for every KPI that has a meter.
Mark a KPI without a meter as `unavailable: <reason>`, never as zero.
3. Freeze: engine SHA, wasm hash, three version, template hash, pose, viewport 1920x1080, tier
`high`, warmup, sample windows, and the GPU identity (`TN_GPU_CLASS` nvidia/turing).
4. Run the unchanged pair (legacy arm and Wasm arm) at least three times, alternating order.
Set the noise margin from these runs before you write any code.

## Finding the next lever

Tempest cost is per pixel: at 960x540 both engines are about 3.5x faster than at 1080p. So rank
first by GPU work per frame, in this order:

1. **Pass attribution.** Get GPU ms per pass (scene, reflection, MSAA resolve, bloom chain, post)
on both engines. Use timestamp queries where the adapter grants them. Otherwise use ablation:
turn one stage off on *both* arms and diff the deltas. An ablation is diagnosis only and never
ships. The pass with the largest ours-minus-legacy delta is next.
2. **Codegen diff.** For that pass, dump the WGSL that each engine emits for the same node graph.
Compare instruction count, texture samples, loop bounds, precision and redundant work (a value
lowered twice, a constant recomputed per pixel, a branch that three folds and we do not).
3. **Target traffic.** Count render targets, resolves, copies, clears, load/store ops, formats and
sizes per frame against stock three.
4. **CPU and churn.** Do this only after the GPU gap closes, or when CPU ms exceeds GPU ms.

Record the predicted saving before you edit. Use one conceptual change per experiment. Each
behavior change needs a red/green unit test in `packages/runtime-native` (`ctest -R <case>`) or
`packages/three-native` (vitest). A performance number is not a red/green test.

## Confirm and decide

- Rebuild the web engine (`packages/runtime-native/build/web/tn-native-engine-web.wasm`). Install
it into a fresh Tempest scaffold. Verify that the served wasm is byte-identical to the build.
- Run at least three valid pairs, alternating legacy-first and Wasm-first. Run them against the
incumbent, and against legacy for the T1 ratio. An adapter other than turing, or exit 75 after
its retries, makes the pair `invalid`.
- Run the visual judge, then the sentinel template, then the rain playtest set (16 scenarios; the
known red is `lightning`/`thunderVoices` on both engines).
- Keep only if the median improvement clears the margin, the judge returns NEUTRAL or
IMPROVEMENT, the sentinel does not regress, and the tests are green. Commit each kept lever on
the campaign branch with its test.
- Every third experiment, rerun the original baseline pair to detect drift.

## Stop and report

Stop at the skill's stop conditions, or when engine levers stop paying. In that
case, report:

- the per-pass GPU table (ours and legacy);
- the remaining gap to T2;
- each template-side option with its measured saving and the judge's description of how the
image changes. Apply none of them.

Finish with the dashboard link, the KPI table (baseline, incumbent and delta per KPI), the
accepted and rejected counts, and one next action that someone can resume.

## Arms, lanes and frozen scenarios

Paths are relative to the owning ThreeNative checkout. Check the current CLI help before you use
a flag. These are routing pointers.

### Arms

| Arm | How to make it | What it proves |
| --- | --- | --- |
| Wasm engine (candidate) | Scaffold `rain` with the local framework. The default engine is native. | The engine under test |
| Legacy (control) | The same scaffold with `engine: "legacy"` in `threenative.config.ts` | Stock three.js WebGPURenderer on the same template revision |
| develop (optional) | Scaffold from `origin/develop` in its own worktree | A third view when the template itself changed |

Scaffold the same way that `scripts/verify-template-playtests.ts` does: `createProject({ install:
true, packageSources: await packageLocalFramework(root), target, template: "rain" })` from
`packages/create-threenative/src/index.js` and `scripts/visual-gate.js`. Use a fresh temporary
root for each arm. Serve each arm with `pnpm exec vite --host 127.0.0.1 --port <port>
--strictPort` from its project directory.

Confirm each arm by what it loads, not by its config. The Wasm arm imports the
`threenative:web-engine` module. The legacy arm imports `three_webgpu.js` from `.vite/deps`.

### The web lane (primary)

- Use the playtest runner's own Xvfb. Unset `TN_PLAYTEST_HOST_DISPLAY`. Never use the owner's
display or the laptop display.
- Pass `--browser-recipe webgpu --headed`. Without `--headed`, Chromium can fall back to
SwiftShader.
- Every run must report the reference adapter in `adapter.info`. On João's machine this is the
RTX 2080: vendor nvidia, architecture turing. Any other adapter makes the run `invalid`.
- Exit 75 means that the capture lock is busy. Retry it. Set `CAPTURE_LOCK_TIMEOUT_MS` to wait
longer. Other agents share the GPU, so do not run two arms at the same time.
- With `assert.performance`, the runner adds `--disable-frame-rate-limit` and
`--disable-gpu-vsync`. GPU ms is then the uncapped cost. The presented interval of a 60 Hz claim
needs a vsync-on run.

### The desktop lane (T3)

Build the V8 player (`pnpm native:build`). Run the scaffold with `pnpm build --target desktop` and
`THREENATIVE_ENGINE_PLAYER` set to the player. Use the playtest runner's `--target desktop` with
the template's `native-playtests/` (`boot`, `lightning`). Read frame windows with
`node packages/playtest/dist/runner/cli.js perf --file <log>`. Use the legacy browser arm as the
comparison, and label it as a cross-runtime comparison.

### Frozen scenarios

| Scenario | Use |
| --- | --- |
| `playtests/performance.playtest.json` | Primary timing: 1920x1080, `high` tier, 60 warmup frames, a walk, then 600 ticks |
| A pose scenario (viewport 1904x960, warmupFrames 30, waitTicks 300, one `pose` screenshot) | Visual judge and parity diff. Save it in the campaign directory and hash it. |
| `playtests/storm.playtest.json`, `weather.playtest.json`, `tiers.playtest.json` | Second Tempest load levels: heavy storm and each quality tier |
| The full `playtests/` set | Behavior gate before keep |

### Known state (2026-10-16, engine 54c226867)

These numbers start the history. They are not a baseline for a new campaign: measure your own.

- GPU ms at 1920x1080: Wasm 113.6, legacy 43.5 (3 pairs). CPU ms is equal on both arms.
- At 960x540, both arms are about 3.5x faster, so the cost is per pixel.
- `reflections: false` saves about 19 ms on Wasm and 5 ms on legacy. About 55 ms of the gap has
no named pass yet.
- Pose parity against stock three: full-frame mean diff 0.006 after the mat2 order fix.
- The rain playtest set passes 15 of 16 on Wasm. `lightning`/`thunderVoices` fails on both engines.
- Stock three itself is near 30 fps on the reference GPU, so T2 means beating stock three by more
than 2.5x.
4 changes: 4 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
packages/runtime-native/patches/*.patch -text
# Unified-diff context prefixes precede the upstream bundle's tab indentation.
patches/vite@8.2.0.patch whitespace=-space-before-tab
packages/three-native/tests/compatibility/goldens/** linguist-generated
packages/three-native/tests/compatibility/fixtures/** linguist-generated
packages/three-native/api/*.json linguist-generated
packages/three-native/generated/** linguist-generated
Loading