Repository navigation
feat(render): S5e + Extract-free — GPU frame in the unified scheduler - #10
Conversation
…#8343) Quality gate red on clippy/test: rustpython-vm 0.5.0 (latest published) does not compile against libc >= 0.2.187 — POSIX_SPAWN_SETSID on linux-gnu became c_short (i16) while nix 0.30 PosixSpawnFlags is a c_int bitflags: error[E0308]: mismatched types (expected i32, found i16) rustpython-vm-0.5.0/src/stdlib/posix.rs:1812 The outdated stage is a hard gate (all deps latest), so pinning libc back is not an option; no patched rustpython-vm release exists (0.5.0 is max_version, 2026-03-31) and main's fix rides on an unpublished refactor. Fix: vendor the published 0.5.0 sources (RustPython tag 0.5.0, 39a6486) into third_party/rustpython-vm with exactly the upstream fix from RustPython#8343 applied (.into() on POSIX_SPAWN_SETSID) — diff vs tag is that one hunk. Wired via [patch.crates-io] path source (deny.toml allows path deps, allow-git = []; cargo-outdated/audit skip path deps). Workspace exclude prevents auto-membership (clippy -D warnings / fmt / test stay off third-party code); rustqual.toml excludes third_party/** from the ratchet; Cargo.lock swaps the entry to a path source. Delete third_party/rustpython-vm + the patch section when a compatible rustpython-vm release is published (README there has the checklist). Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
|
❌ Quality gate failed on 📊 QUALITY SUMMARY📜 Tail of log (200 lines)Full logs are in the |
Full quality.log (run 34149520691) — part 1/6
|
Full quality.log (run 34149520691) — part 2/6
|
Full quality.log (run 34149520691) — part 3/6
|
Full quality.log (run 34149520691) — part 4/6
|
Full quality.log (run 34149520691) — part 5/6
|
Full quality.log (run 34149520691) — part 6/6
|
| (stale part — log got shorter) |
The S5d/S7 commit added crates/render/src/gpu_resources.rs storing wgpu Device/Queue/Surface/CommandBuffer/Renderer3D as World resources, but wgpu's web backend types are !Send/!Sync (Rc, JS callbacks) while World::insert / Resources::get / SystemAccess require Send + Sync — 26 x E0277 on cargo check -p ornis-wasm --target wasm32-unknown-unknown. Hidden on master by the 10-annotations-per-step cap (clippy/test flood from the rustpython-vm break); the PR digest summary exposed it. Native-only module: the only consumer outside ornis-render is the native root binary (src/main.rs); the wasm path renders through RenderWorld extraction + ornis-wasm, as before S7. Same convention as frame_exec.rs cfg pairs. Docs synced (README, unified-scheduler.md). Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
|
✅ Quality gate is green — run 34107349433 passed all 13 stages (fmt / clippy / rustqual / smoke / test / test (physics gpu) / clippy (physics gpu) / audit / deny / outdated / doc / wasm-check; upgrade-check = SKIP, cargo-upgrade not installed in CI — pre-existing). The ❌ digest + log chunks above are from the previous (intermediate) run and are kept for history — the workflow only overwrites them on failure. |
First step of the S5e + Extract-free decomposition (docs/rendering/unified-scheduler.md): the pass-as-system adapter. - schedule_bridge: try_project_schedule(&SystemSet) mirrors every enabled pass into a core Schedule PassSystem twin — same name, accesses projected from ResourceId to the FrameResource TypeId via the registry. Disabled passes drop out with their edges, mirroring layout_levels exactly; untyped resources are an honest ProjectionError (nothing to mirror). run() is a no-op declaration twin by design — E2 moves recording into systems via FrameCommandBuffers. - RenderFrame3D::render_schedule: renders a frame ordered by the projected Schedule levels (flatten → execute_in_order), recording through the caller's borrowed encoder — same dispatch_pass as the sequential/parallel paths (extracted into PassDispatch). Debug-assert pins projected levels == FrameLayout::levels() every frame. - Gates: scheduler_parity extended with the E1 canon (projection == layout levels on chains/shared-levels/edge-splits, disabled-pass culling, untyped rejection) + production Technique×bloom matrix in bridge unit tests; tests/schedule_render.rs pins pixel identity schedule-driven vs sequential on lavapipe (harness mirrors the S5b parallel_render gate). - Docs: unified-scheduler.md E1 section marked done, README row synced. Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
|
❌ Quality gate failed on 📊 QUALITY SUMMARY📜 Tail of log (200 lines)Full logs are in the |
… harness Three findings from the E1 gate run, fixed at the source: - system.rs: resource_type used an explicitly-dereferencing pattern inside an implicit borrow (edition 2024 hard error); the find closure now compares through the double reference instead. - fmt: schedule_bridge module/use sorted to rustfmt order in lib.rs, two wrap forms in bridge/parity restored to rustfmt's preference. - rustqual ratchet (+25 findings): tests/schedule_render.rs was a near-verbatim copy of parallel_render.rs — DUPLICATE exact + a dozen FRAGMENTs. Extracted the shared headless-GPU harness into tests/common/mod.rs (scene, targets, readback, render_frame_pixels, with_headless_scene skip entry, sequential_reference_pixels); both gates are now ~30 lines of unique logic each. Removes the pre-existing duplicate/fragment findings from parallel_render.rs too, so findings land below the 1813 baseline. render_schedule is now fallible (Result<(), ProjectionError>, # Errors documented) instead of panicking — the projection failure is a declarable error, and the gate test's expect is not flagged in test code. Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
|
❌ Quality gate failed on 📊 QUALITY SUMMARY📜 Tail of log (200 lines)Full logs are in the |
….33.7 - scheduler_parity: unwrap_err() on Result<Schedule, _> requires Schedule: Debug (it isn't, and shouldn't need to be) — switch to .err().expect(), Option::expect has no Debug bound. - glam 0.33.7 released 2026-09-07 12:05 UTC; the outdated stage is a hard gate, so bump the lock entry (all workspace requirements are caret 0.33; 0.33.6 lock entry had no active optional deps, 0.33.7 same features — version+checksum swap only). Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Recording moves off the borrowed encoder on the native runtime path: per-pass encoders land in FrameCommandBuffers (registration order), RenderPresent hands the acquired frame to FramePresentTarget, and the new RenderFlush system does the single ordered submit + present (WaW on both handover resources, registration order). - FrameExecutor::record_in_order — sequential form of execute_parallel mechanics (own encoder per pass, buffers pushed in registration order) - RenderFrame3D::render_to_buffers — second recording form over the shared projected_order helper (no submit); borrowed render() stays for wasm/examples/benches - FrameCommandBuffers::flush — drain + single ordered submit - RenderPresent: acquire → reconfigure-on-Outdated/Lost → render_to_buffers → stash into FramePresentTarget - gate: third pixel-parity test on the shared GPU harness (sequential reference vs buffers+flush) - docs: unified-scheduler.md E2 section + README row Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
First Extract-free step: upload data no longer round-trips through the Mutex<RenderExtracted> snapshot clone. RenderSubmit declares reads_lane on TransformDesc/MeshDesc/MaterialDesc (S5d canon, same shape as RenderExtract) and calls the shared extract_render_data canon on the SmartStore at submit time. Ordering vs lane writers is now lane-granular RaW instead of RaW on the whole snapshot. RenderExtract/Mutex<RenderExtracted> stay as the oracle; the gate test pins a direct extract_render_data call byte-equal to the snapshot the scheduled system published (materials as Pod bytes, instances field-wise; three material kinds, varied tessellation). docs: unified-scheduler.md X1 section + README row Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Mesh + tessellation cache move out of GpuFrameState into a standalone Mutex<GpuMesh> resource: re-creation no longer holds the renderer/frame plan lock (documented lock order: GpuMesh before GpuFrameState). - max_mesh_params in extraction.rs: the re-create criterion as a canon alongside extract_render_data — max tessellation over COMPLETE entities only, (32, 24) floor; iterator form (lane walk in closures) - new RenderMesh system (install_render_mesh): reads the three lanes (S5d canon), writes only Mutex<GpuMesh> - RenderSubmit drops the mesh re-create (and its GpuDevice read); RenderPresent reads the mesh resource (RaW after RenderMesh), the unsafe split-borrow narrows to renderer + frame3d - gates: canon-tie unit test (incomplete 96/64 entity must not move the maximum) + tessellation probe on the shared GPU harness (tests/mesh_resource.rs: 48/32 -> +16/12 no-op -> +64/40 re-create, vertex/index counts vs a reference sphere) - record_in_order: PassViews inlined into the run() call, mirroring execute_in_order exactly (delegation-only loop body) docs: unified-scheduler.md X2 section + README row Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
RenderSubmit no longer hardcodes set_lights: ambient + directionals come from the new RenderLights resource, written by the scene loader between frames (RenderWorld::replace_scene publishes scene lighting; RenderLights::from_scene is the shared constructor) and only read inside the schedule — no Mutex, same contract as GpuSurfaceState. - RenderLights::default reproduces the legacy hardcoded rig via consts (install_gpu_resources inserts it: a runtime without a scene renders exactly as before) - set_lights_args is the single LightDesc -> (direction, intensity, color) conversion; wasm's build_gpu_scene migrates onto it (the inline match is gone) - gates: unit tests (default == legacy args; replace_scene publishes scene lighting) + pixel probe tests/light_resource.rs on the shared GPU harness — legacy hardcoded arguments vs the resource through set_lights_args must be pixel-identical docs: unified-scheduler.md X3 section + README row Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…shot Extract-free finished: the render frame payload is read straight from the component lanes; the scheduled snapshot round-trip is gone. - RenderExtracted renamed to FrameUpload (a direct-read payload, not a snapshot); the RenderExtract system, the Mutex<RenderExtracted> resource and install_render_extract are deleted - RenderWorld::extracted() -> frame_upload() (extract_render_data on the world's store); RenderWorld stays the scene-loader host — its schedule is empty now - RenderPresent (the last snapshot reader) reads SmartStore + the three lanes (same access shape as RenderSubmit/RenderMesh); the instance count comes from extract_render_data directly - wasm: GpuScene.extracted is a FrameUpload, build_gpu_scene and the contract test use frame_upload(); schedule().len() == 0 asserted - net quality effect: one error-handling finding removed (RenderExtract ::run), none added docs: unified-scheduler.md X4 section, checklist E3 no-op noted, the decomposition header closed; README row Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
|
❌ Quality gate failed on 📊 QUALITY SUMMARY📜 Tail of log (200 lines)Full logs are in the |
CI on ac33ca0 (run 34147754661) failed fmt, clippy, rustqual and test: - fmt: apply the canonical rustfmt shapes (import ordering with cfg attributes, collapsed filter closure, split let-pattern, multiline export list, three-line assert_eq with message, exploded tuple). - clippy: drop two stale 'mut' bindings; render_to_buffers took 8 arguments — group its inputs into BufferRenderContext (native-only, published from frame_exec). - rustqual: RenderSubmit::run regressed to an IOSP Violation (logic + own call) after X1/X3 — extract the camera math into camera::camera_view_projection (pure math, no own calls) with a unit test; run() is pure orchestration again. - test: the root showcase package (src/) still used the deleted snapshot API — install_gpu_resources gains the GpuMesh resource (7 args), GpuFrameState drops mesh fields, engine_runtime tests read lanes directly via extract_render_data; the physics-ordering test is renamed to physics_sync_output_is_visible_to_render_lane_reads. - docs: X4 section notes the root-package migration; stale 'oracle stays' wording corrected. Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
|
❌ Quality gate failed on 📊 QUALITY SUMMARY📜 Tail of log (200 lines)Full logs are in the |
- clippy -D warnings: the light_resource gate binary does not use the shared sequential reference (its subject is the legacy rig, which the harness does not bake), and mesh_resource uses only the device part of the harness — annotate 'mod common' with allow(dead_code) and a comment in both, matching the shared-harness-subset reality. - fmt: split the world.engine_mut().world_mut().insert chain in mesh_resource (chain width). Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
…rics Green-run summary (CI 34150634051 lineage, 13/13 PASS): - quality_score 15.9% -> 17.9% (0.17868384215287147) - iosp_score 92.2% -> 92.4% (0.9235820895522389) - total_findings 1813 -> 1807, violations 128 (unchanged) - functions 2587 -> 2640; violation_details re-pinned to current lines (128 entries). Values reconstructed from the run summary (all seven dimension percentages match the printed block bit-for-bit; scores recomputed with the exact rustqual formulas and rustqual.toml weights). Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
All five review questions are answered by the shipped implementation: module-inside-render confirmed, immediate per-frame plan confirmed, pool keyed by the full TextureSpec, sub-pass deferred (no wgpu input-attachments), debug dump delivered as the shared S6 mermaid() projector instead of a bespoke JSON dump. Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Closes the final phase of the Unified Scheduler roadmap (
docs/rendering/unified-scheduler.md): the S5e + Extract-free decomposition.Main part — S5e + Extract-free (E1–E2, X1–X4, E3)
Schedulesystems:schedule_bridgemirrors every enabled pass into a typed-access twin (disabled passes drop with their edges);render_schedulerenders by the projected levels; level parity is debug-asserted every frame.FrameCommandBuffersin registration order, one ordered submit+present inRenderFlush;render_to_buffers(BufferRenderContext).RenderSubmitreads theTransformDesc/MeshDesc/MaterialDesclanes directly through the sharedextract_render_datacanon — no moreMutex<RenderExtracted>clone.GpuMeshresource +RenderMeshsystem: the sphere is re-created whenmax_mesh_paramsmoves (floor 32×24);GpuFrameStatekeeps only renderer + frame3d.RenderLightsresource (ambient + directionals, published by the scene loader; the default reproduces the legacy hardcoded rig bit-for-bit).RenderExtracted→FrameUpload: the snapshot system and resource are deleted; wasm and the root showcase migrated to direct lane reads; the render side now registers zero scheduled systems.Gates: ~15 new (pixel parity ×3, canon-tie, tessellation probe, light probe, scheduler parity, unit tests). CI Quality 13/13 green; ratchet improved — quality 15.9→17.9%, IOSP 92.2→92.4%, findings 1813→1807, violations 128 (flat). Baseline re-pinned to the new metrics.
Prerequisite — unblocking the Quality gate
rustpython-vm 0.5.0+ the upstream libc fix (RustPython#8343): the published crate does not compile against libc ≥ 0.2.187 (POSIX_SPAWN_SETSIDbecamec_short), and theoutdatedstage forbids pinning libc back.gpu_resourcesoff on wasm32 (wasm-check): wgpu web types are!Send/!Sync.