Files
solvecraft/docs/render-jobs.md
selune 9e6e0b8df1 Render workspace: complete experimental ribbon, resources and effects integration (#5493) (#5494)
* wip(render): reconcile completed material and image pipeline source with 0.20 (#5493)

Source-only integration reference for staged review, not a merge-ready aggregate.
Donor: 0xlillith/solidcraft@aea20b0115.
Upstream: 858e5995d6.

Retain original CPU/material contracts and explicit GPU donor provenance in
docs/render-materials-lab.md (#2067, #2191, #2780, #3306). Preserve released
format migrations and current navigation/startup/shell behavior. New saved
records use pending descriptors. The physical-card descriptor follows the
maintainer's material-engineering-cards naming request, with a legacy-lab
format-29 regression. Replace raw new panel hosts with shared containers.

Repository checks, complete workspace/all-target Clippy, and the independent
physical/resource authoring checks pass for this source. The fresh full local
CI invocation has reached test compilation and is not yet complete. Do not
transfer donor native output or prior test totals to this integration.

Generated review screenshots, video, package ZIP and machine logs remain at
the immutable personal evidence pin. Uncommitted geometric displacement is
backed up separately, not silently included. No kernel/vendor change, direct
main write, release or independent contributor-branch rewrite.

Co-authored-by: Christian Svensson <blue@cmd.nu>

* test(cli): pin the Compact camera-sample admission diagnostic (#5493)

The bounded request still refuses 1024x1024x64 samples before host initialization and writes no output. Update only the stale expected diagnostic to the existing Compact budget wording; production limits and code are unchanged. Exact-tree CLI regression suite: 14 passed, 0 failed. The full repository gate has been invoked separately and is not yet complete.

* Normalize UI container violation paths across platforms

Report repository-relative paths with forward slashes so diagnostics and the existing nested-package regression assertions agree on Windows and Unix. Keep the container detection rules unchanged.

Validation: official ui-containers gate and all seven focused xtask tests passed; rustfmt and diff checks passed. Only xtask/dependencies were compiled; no application build or heavy tests.
(cherry picked from commit 44b58d8e10)

* fix(render): preserve camera contracts and correct acceptance regressions (#5493)

Preserve Design view.apply semantics with a separate strict Render camera command. Retain existing translations when English-only aliases collide; add material-axis entries and camera-specific pitch labels. Compare complete validated engineering cards and retain job handles before cancellation.

Focused and native acceptance is pinned to tree f8a423b21f. Full CI has been invoked separately and is not claimed green. Landing follows the render integration policy in #5493.

* fix(render): resolve showcase licence and upstream resource hygiene (#5493)

Record SychPL's explicit MIT OR Apache-2.0 grant, retaining source/model bytes and the Ubuntu lettering notice. Remove 80 absent attribution rows, personal fork records, dead delivery attributes and three fork/resource-only workflows. Existing xtask assets now performs bounded offline hash checks and rejects orphan render attribution; no parallel draft CI or package installation. Original authoring reproduction remains explicit. Scoped xtask tests, assets, Clippy, formatting and prepared SELENE validation pass; no application or renderer-wide result is inferred.

* fix(render): align saved bounds and progressive sample resolution (#5493)

Address review r4364211669/r4364211677/r4364211681/r4364211691/r4364211695. Persisted light/frame domains respect the existing 1e9 document bound; related LED/rectangle/direction cases use the same bound. Workstation primary resolve shares the 4096 admission cap and film counters use checked conversions. Exact candidate: 485 CPU render tests, 21 render document tests and strict scoped Clippy pass, including positive boundary round trips and 2048/4096 end-to-end checkpoints. No released format/migration edits, relaxed test limits or full-stack acceptance claim.

* wip(render): isolate optional resources and harden sample handling (#5493)

Review work in progress: opt-in encoded render library with reproducible runtime catalog exports; native-only robust dependency through the workspace; checked bloom slices; per-sample point-light diagnostics; independent area-light spatial/film keys. Resource-module binaries in both configurations, generation, Cargo production feature graphs and attribution checks pass. Full engine/render regression and combined acceptance are pending: do not merge this donor as a constituent or treat scoped resource proof as runtime acceptance.

* fix(gpu): preserve donor allocations through the scope-safety repair (#5722)

Port the native-validated #5723 scope-cleanup correction into the experimental donor, retaining its adaptive, volume, aging, photographic and bloom allocations. Same reverse-drain helper and regression cases; the donor combination still needs its own compile/test gate and is not covered retroactively by render-base results.

* claim: #1369

* Reject unknown pending concepts after format folding (#1369)

* test(render): close bounded sampling and bloom review regressions (#5493)

Validate the optional-resource/lighting/dependency donor at its exact tree. Required Vulkan GPU 127/0/3; CPU renderer 487/0; engine Render 72/0; document render 21/0; lean library 7/0; strict scoped Clippy, assets/layers/lists/containers and lean-engine WASM pass. Preserve original failed controller/typing attempts. This is the draft donor/disposition source, not a replacement for constituent render PRs or final main acceptance.

* wip(render): preserve stable aging target validation candidate

Exact staged source from prior review work on donor 3b892eab5e. This is a recovery/review checkpoint, NOT accepted delivery. An actual command-path regression currently fails because the selected executor refuses ordered surface aging. No assertion, capability or admission limit is weakened. Native/UI/full combination acceptance remains pending. Saved/runtime split adds one pending descriptor and retains original file scope; no main/render branch is changed.

* test(render): preserve numeric setup intent at the admitted coordinate bound

Follow up jyviko review on #5494 without weakening the corrected saved-coordinate contract. The positive clicked fixture uses 1e9 instead of inadmissible 2e9; explicit out-of-range cases still refuse, and the full saved setup round-trips through JSON and the native container. Exact-source Render workspace 95/0 and strict all-target UI Clippy pass. This does not incorporate the separately failing stable-aging candidate or claim full current-render acceptance.

* test(render): use the real GPU executor for saved aging

Move successful native cold-reopen Check/Start coverage from the CPU-backed protocol fixture into the production GPU executor tests. Verify capture-index changes preserve the stable target and that enabling aging changes both PNG and raw EXR output. Retain explicit, allocation-free refusal coverage for executors without aging support. Production capabilities and admission checks are unchanged.

* fix(render): persist stable identities for targeted aging (#5493)

Separate saved RenderBodyTarget identities from captured mesh ordinals. Reject legacy ambiguous targets, resolve Check/Start after visibility changes and preserve native reopening, copies and undo. Unsupported executors still refuse; real AMD Vulkan regression completes saved aging after reordered capture.

Source tree 6b84c8ad passes document 23, engine Render 75, GPU effects 5 and Render UI 95 with no failures; scoped strict Clippy, WASM and repository gates pass. Fresh CLI/native reopen and clean/aged GPU exports pass with identical physical totals and inspected actual images. Whole current-render integration is separate.

* fix(render): reconcile combined CPU/GPU contracts on current upstream

Unify captured resources/status and CPU-vs-GPU request schemas after the real two-parent integration; remove obsolete duplicate Vulkan selector and retain combined platform-filter regression. Deduplicate only identical or superseded test definitions, retaining the stronger card metadata and reserved-executor assertions. No assertions, admission limits or feature refusals are weakened.

All targets of render dependencies, GPU, engine, UI, CLI and native app pass cargo check with raytrace-cpu and bundled-render-library at tree c70d00d1. Native executable tests and full current-source acceptance remain pending. This is a private integration rehearsal for subsequent constituent PRs, not an aggregate official render/main merge.

* test(render): retain one complete host lifetime regression set

Deduplicate byte-identical DropProbe/task-lifetime tests and retain the adapted environment/texture ownership regressions with every assertion and complete memory estimate. Keep the registered-geometry admission regression once; only struct field order differed. Replace a one-element diagnostic loop with its equivalent block, preserving all wrap/width assertions.

Test-only integration repair. Formatting and diff checks pass; refreshed executable validation is required. No production behavior, limits, assertions or ignores changed.

* fix(doc): recognize the proven format-29 card descriptor alias

Normalize only the historical format-29 physical-material-cards spelling, and only when material-engineering-cards is registered. Admission and migration de-duplication use the same identity. Unknown concepts, wrong versions and incapable readers still refuse before mutation. Six controlled-history Rust regressions and actual CLI migration/no-clobber acceptance pass. No version, released migration or CI changes. Refs #5793, #1369, #5493.

* test(render): preserve grounding refusal before explicit instance moves

Update the two Render binding fixtures for upstream first-occurrence grounding. Verify grounded movement refuses without changing document/history, then explicitly unground through the public command before the intended move. Retain every target, resource, copy and persistence assertion. Refs #5493.

---------

Co-authored-by: Christian Svensson <blue@cmd.nu>
Co-authored-by: Victor Santos Oliveira <56417388+Vittuu@users.noreply.github.com>
Co-authored-by: cfaulkingham <colin.faulkingham@gmail.com>
2026-10-24 14:21:59 +00:00

8.5 KiB

Product-image jobs (R4a)

Native progressive opaque PNG rendering is described in Progressive product images. It registers alongside the CPU executor.

R4a adds bounded CPU preview images to the Render workspace. The installed builtin / cpu-product executor supports Preview, Image and PNG. It does not promise refraction, HDRI, exposure, final mode or EXR; those requests fail explicitly. The subsequent opaque PBR consumer adds opt-in direct-lit surfaces through the same host. Legacy scalar looks and the Design snapshot renderer retain their existing shading.

One command path

render.preflight and render.start take setup (a saved name) OR settings (a RenderSetup object; omitted fields use its documented defaults), plus optional transparent_background and replace booleans, both false by default. Without either setup/settings, the current requested camera is used, or the camera is fitted to the product. Saving a setup is independent of starting a job. Unknown fields are errors.

Both commands reject stale geometry without settling a live modelling gesture. Finish the gesture or use the explicit render.scene boundary first. Capture uses R3's authoritative visible meshes, placements and appearances, without selection, edges, axes, grids, sections or analysis overlays. A cold capture can prepare world geometry and meshes synchronously; it is not a promise of bounded CAD evaluation latency. Preflight validates capabilities and estimates admission, but does not reserve a queue slot or the host memory pool. Start checks those resources again.

Start returns a typed job: {session, serial, generation}. Keep all three fields when calling render.status, render.cancel or render.export. IDs are never accepted by another document session, scratch copy, or a newly opened/recovered document. Status does no rendering and never waits for completion. It reports queued, preparing, running, encoding, cancelling, cancelled, completed or failed, with phase-local done/total, structured job errors and completed frame metadata. Progress restarts when a phase changes; it is not a time estimate.

The captured scene_generation is the session revision at start. Later edits, undo, camera changes and tab switches do not mutate the snapshot. An image continues to describe that captured scene; the UI labels a revision mismatch conservatively (view cache invalidation can also advance a revision). Runtime state is outside the document, undo, checkpoints and the design format. Closing/replacing a session cancels its work; the worker cannot publish a cancelled frame. Direct host-side document replacement preserves the installed image service while allocating fresh job ownership; old IDs and completed images never cross into the new document. replace: true cancels retained active and pending jobs before submitting the new request. A cancelled generation cannot publish late. A successful older generation never replaces a newer successful result.

Each document retains at most two live jobs, four recent terminal status records and one last successful image. Cancellation/failure preserves that image. A new successful image releases the previous image; old terminal metadata can still report completion, but it does not promise that its bytes remain exportable. Export requires an explicit retained completed job ID; it never silently exports a different/newer job.

Native CPU raytracing can separately enable progressive camera sampling. A status may then include preview: {frame_sequence, samples_per_pixel, frame}. Its complete-pass PNG is available through the in-process JobHandle::preview() consumer; the JSON status contains metadata only. The preview keeps the same job and capture identity, but remains separate from the retained final image and render.export. Cancellation, failure and final publication clear the provisional slot while preserving the previous successful result when no newer final exists. Each externally retained preview keeps its own admitted memory reservation.

Native and browser execution

Each application installs one CPU host, shared by its documents. Native execution uses one worker and at most two queued inputs across documents; it runs without UI polling. The browser uses the same incremental task, pumped by UI frames, without threads. Preparation, stable transparency sorting, clearing, pixel tests and downsampling check cancellation between small units. A step admits at most 16384 units; PNG encoding additionally yields after four rows. The UI pumps 1024 units per frame. These are work bounds, not hard real-time guarantees: allocation, codec compression and OS scheduling still have platform-dependent latency.

Admission caps output at 4096 per dimension and 4 million pixels; pixel scratch is estimated at 48 bytes per output pixel (2x supersampling). Other limits: 262144 triangles/face overrides/edge polylines, 128 MiB retained source geometry, 384 MiB total estimated memory per job, 512 MiB shared host admission including retained PNGs, and 128 million projected pixel tests. The projected-work limit is checked during bounded preparation and may fail an admitted job. Encoded PNG bytes have an additional 8 * output_pixels + 65536 cap. Allocator and codec internals are estimates, not an operating-system memory quota. Limits fail with errors rather than allocating unbounded buffers. Completed frames keep their memory reservation while bytes are retained.

The CPU path shades in linear light, blends sorted triangle alpha approximately, then encodes 8-bit sRGB with straight alpha and an sRGB PNG chunk. Transparent shared edges use a consistent fill rule. Intersecting transparent surfaces and triangle sorting remain raster approximations. This is not a glass/refraction renderer. Native GPU preview and CPU export can differ in shading and transparency.

PNG uses the already-transitive Rust png crate (MIT OR Apache-2.0), now an explicit render dependency. No external render engine or third-party art is introduced.

Export and automation

render.export takes job, path ending in .png, and overwrite (default false). The destination is checked against the caller's existing file-access scope before reading the retained frame or calling either native writer. Disallowed folders and traversal are refused in both overwrite modes. Native no-clobber export writes/syncs a temporary beside the target and publishes it with an atomic hard link; an existing destination wins even in a race. Filesystems without that operation return an error. Explicit overwrite uses the existing atomic writer without reading or backing up the previous target. Failed writes preserve the completed image and CAD state. Browser export uses the existing virtual file/download service; image-export paths or frame payloads are not persisted in the design. Saved HDR input resources use their separate document contract.

The Render panel provides Check Render Request, Start Render, phase progress, Cancel Render and Export PNG. Replace existing file is an explicit opt-in. A failed or cancelled new render leaves the previous successful export available.

Native PNG export in the combined integration uses the document-bound asynchronous picker from #1114. The requested job ID and overwrite choice are captured before the dialog opens: cancellation writes nothing, closing the originating document drops the answer, and an evicted image fails instead of substituting a newer result. A tab switch does not redirect the export to another document.

Controls and phase messages use stable offline catalog IDs in English, Japanese, Chinese, German and Korean; command IDs and scenario handles remain unchanged.

solidcraft-cli render examples/render-studio.json --out product.png --width 800 --height 600
solidcraft-cli render design.solidcraft --setup Studio --out product.png --transparent

The CLI follows preflight/start/native wait/export, with a default 120-second wait limit (--timeout 1..3600). Timeout requests cancellation. --overwrite is required to replace an existing target. A persistent headless MCP session installs the same host: use the ordinary execute tool with the five commands and returned job ID. Closing the CLI/MCP process ends its session; a one-shot exec render.start is not a durable background service. In a browser, leave the app running so frames can pump work.

Validation evidence and responsiveness measurements are recorded in the R4a issue/PR; passing native tests or a wasm compile does not establish browser visual performance.