Render follow-ups drain (re-applied on 0.19): UiTransform paint + degraded effect groups#75
Merged
Merged
Conversation
…n 0.19] Re-applies the UiTransform-affine-paint follow-up on the Bevy 0.19-rc render pipeline. It was implemented on 0.18 (stale PR #71, closed) but the BSN/0.19 migration rewrote the render plumbing; a fresh investigation confirmed the gap still exists on 0.19 and the design ports verbatim (the migration left PackedInstance at 52B/13-floats and the WGSL shader structure untouched). Render now consumes the full 2D affine GlobalTransform composed by the bridge, instead of dropping all but translation -- so a rotated/scaled UI element paints correctly. extracted_node_for reads global_transform.affine().matrix3 xy columns (pillar-5: GlobalTransform, never a ResolvedTransform re-read, so render == picking). ExtractedNode.affine flows through PackedInstance, the bucket raw record (now 17 floats), packed_to_raw, the prepare RawBufferVec, the quad vertex layout (array_stride 52->68, attrs at locations 8/9), and both quad + shadow WGSL (corner = rect_pos + mat2x2(affine) * box-local corner). Constraint (R2 depends on it): the affine basis is APPENDED after the existing 13 floats so every field offset is unchanged -- color stays float 4, alpha float 7, named COLOR_FLOAT_OFFSET / ALPHA_FLOAT_OFFSET consts. Identity affine = [1,0,0,1] -> existing pixels byte-identical; 4 instance-hex snapshots re-blessed with the trailing identity floats. The 0.19-only immediate_size pipeline field is orthogonal and untouched. Scope = transform-paint only. Residuals kept open: transform-origin (layout 6e does not bake ui.origin -> rotated elements pivot top-left); skew / general TransformMatrix::Matrix (bounded by the bridge's TRS-only decompose); perspective / Preserve3d / BackfaceVisibility (C-tier). clip-and-transform.md B.5 + follow-ups.md narrowed to transform-paint LANDED. Cross-crate: buiy_verify ExtractedNode/PackedInstance sites + snapshot tests updated. Verified on 0.19: clippy --workspace -D warnings clean; render + lib + buiy_verify suites green; GPU rotate/scale reftest passes on the RX 6700 XT (was only compile-checked in the slice; run here to close the loop). R1 lands before R2 (hard PackedInstance-offset dependency). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DHcf8nQ9PTT3m5E7u3Q6XV
…ed on 0.19] Re-applies the degraded-effect-groups follow-up on Bevy 0.19-rc (0.18 impl was on the closed stale PR #71). Builds on R1 (86c995c): the [f32;17] PackedInstance layout + ALPHA_FLOAT_OFFSET now exist. Gap confirmed still present on 0.19 (node.rs still skipped degraded groups; compositor had no fold); ports near-verbatim since the 0.19 ViewNode->buiy_pass migration left the skip site's logic identical (the node edit is comment-only). A budget-degraded effect group (no pooled target) used to vanish; it now folds group.opacity per-instance (re-tint-in-place) and merges its ranges into the flat draw, for ROOT-degraded groups (parent==None). prepare_effect_groups grew RtPoolBudget/RenderQueue/ResMut buffers/ExtractedGlyphs/ExtractedTextQuads params (all present on 0.19) and reconstructs the same quad_dirty/glyph_dirty signals prepare.rs uses. Per-tier dirty gates (the load-bearing correctness point): the alpha-FOLD gates on the buffer-repack signal (quad fold on quad_dirty, glyph fold on glyph_dirty), the range-MERGE gates on the partition-rebuild signal (quad_dirty || glyph_dirty) - distinct so a retained-already-folded glyph buffer does not re-fold (drift to black) yet its range still re-merges on a quad-dirty-only frame (does not vanish). Glyph alpha uses GLYPH_ALPHA_FLOAT_OFFSET=11 (color[3]), not quad's 7. Scoped to ROOT-degraded; a nested degraded child needs a different draw path (composite into the parent's off-screen target) - debug_assert-guarded + release-skip + filed as a new follow-up section. The GPU glyph-idempotency test asserts WHITE-INK red+green stability (NOT the blue background the fixture mutates - the assertion bug that false-failed CI on 0.18, fixed here). Verified on 0.19: clippy --workspace -D warnings clean; render_compositor 35 + render_effect_groups 16 headless; all 4 GPU tests pass on the RX 6700 XT (degraded_glyph_fold_idempotent + range_remerges + no-compound + nested-no- corrupt). effect-compositor.md 2.3 As-landed + follow-ups.md LANDED + nested follow-up. Final render-track slice. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DHcf8nQ9PTT3m5E7u3Q6XV
intendednull
added a commit
that referenced
this pull request
Jun 19, 2026
Final doc pass. All 13 actionable slices landed (layout #69, text #74, render #75 re-applied on Bevy 0.19-rc); each slice already flipped its own follow-up entry to LANDED via the per-slice commits. This pass reconciles the remainder: - Flip the superseded "anchor target IS sticky/table/multicol" entry to LANDED (closed by Phase 7 Task 9 / the PostTaffyPositionOverrides shared correction buffer = Option 1 of its own sketch; tested in layout_sticky.rs). - Document position_try_max_depth as Deferred-not-built with a re-open trigger (speculative: gated on unmeasured profiling -> a cap is an unused knob). - Add re-open triggers to the multi-reference-reftest-aggregation and golden-prune deferred entries (tested-but-unused / nothing-to-prune-yet). - Flip the campaign plan to landed (doc + README catalog [active] -> [landed]). node-draw-model was already LANDED; the build-item entries were verified LANDED (spot-checked all 13). Blocked items (cross-window anchor, per-window top layer, sticky em/rem/V* insets, clear_warned_once, R11 BoxShadow draw-skip, multi-range selection, nested degraded composite) remain correctly documented as gated on their unbuilt subsystems / renderer features. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DHcf8nQ9PTT3m5E7u3Q6XV
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Render track of the follow-ups-drain campaign (
docs/plans/2026-06-18-followups-drain.md), re-applied on Bevy 0.19-rc. The original render PR (#71) was built on 0.18 and went stale when the BSN/0.19 migration (#72) rewrote the render pipeline; #71 is closed. A read-only investigation confirmed both gaps still exist on 0.19 and that the design ports verbatim/near-verbatim (the migration leftPackedInstanceat 52B/13-floats and the WGSL shader structure untouched).Slices
86c995cUiTransform affine paint (rotate + scale) — render now consumes the full 2D affine fromGlobalTransform(pillar-5: never aResolvedTransformre-read, so render == picking) instead of dropping all but translation. The affine basis is appended after the existing 13 floats so every field offset is unchanged (alpha stays float 7, namedCOLOR_FLOAT_OFFSET/ALPHA_FLOAT_OFFSET); identity affine → existing pixels byte-identical (4 instance-hex snapshots re-blessed). Quad + shadow WGSL transform the corner about box-local origin. Residuals kept open: transform-origin (layout-side), skew/general-Matrix (bridge TRS decompose), perspective/Preserve3d/backface (C-tier).c1d1fe8degraded effect groups forward-composite flat — a budget-degraded group used to vanish; it now foldsgroup.opacityper-instance and draws flat (effect-compositor.md §2.3), for root-degraded groups (nested deferred → debug_assert + new follow-up). Per-tier dirty gates prevent compounding alpha drift; glyph alpha usesGLYPH_ALPHA_FLOAT_OFFSET=11 (not quad's 7). R2 builds on R1's PackedInstance layout.Verification
cargo fmt --all --check,cargo clippy --workspace --all-targets -D warnings,RUSTDOCFLAGS=-D warnings cargo doc --workspace --no-deps, andcargo test --workspace(185 ok / 0 failed) all green on 0.19. The GPU reftests (render_transform_paint_gpu,render_degraded_group_gpu) pass on the local RX 6700 XT — includingdegraded_glyph_fold_idempotent_under_quad_dirty_only_frame, whose assertion was corrected (white-ink R+G stability, not the mutated blue background) before it broke CI on 0.18. The pinned-lavapipe GPU CI lane exercises them here.🤖 Generated with Claude Code