Conversation
|
this branch causes GPU faults on my RX580 (your branch separately and also when merged with current master which touches adjacent code) |
|
when I log in with restore session on, and systemsettings was open, immediate GPU crash that takes the system down, every single time: |
|
Hypothesis: per-frame descriptor-pool exhaustion MAX_DESCRIPTOR_SETS_PER_FRAME = 1024 (crates/yserver/src/kms/vk/pipeline.rs:119) is not merely advisory — it sizes each per-output descriptor pool, via CompositePoolRing::new(..., MAX_DESCRIPTOR_SETS_PER_FRAME) at crates/yserver/src/kms/render/scene.rs:647. Every emitted CompositeDraw consumes one descriptor set (record_descriptor_allocations(built.scene.draws.len()), scene.rs:~1868). The 64-rectangle / bounding-box fallback this PR removes was therefore load-bearing for that budget, not only a performance guard: it bounded draws.len() per window. With it gone, one shaped window can emit thousands of draws — this PR's own regression test constructs a 65x65 vertical/horizontal stripe intersection, i.e. 4225 rects from a single window, 4x the entire per-output pool. Why this reproduces here and not on your setup — three configuration differences:
If a frame's descriptor demand exceeds the pool, sets are exhausted or recycled while a prior submission is still in flight; the GPU then dereferences a stale image descriptor and samples a recycled BO. That produces exactly the observed signature — a VM_CONTEXT1 protection fault reading from the texture cache, at a constant GART address, attributed to whichever process owned that memory. Which is why it looks like a client bug and why the named process varies. Verified: the constant and its role in sizing the pool, one descriptor set per draw, the cap removal, the 4225-rect test, KWin's full-framebuffer COW shape, and the 3/3-vs-clean A/B. Inferred: that descriptor exhaustion specifically is what corrupts. Cheap confirmation would be logging draws.len() per frame per output and checking whether it crosses 1024 shortly before the fault. Suggested direction Please don't reinstate the extents fallback — the reasoning for removing it is correct, replacing an exact region with its bounding box paints outside the mask and violates SHAPE. The problem is one draw per rectangle, so either:
The second is the more robust fix, since it also removes the per-frame cost of a complex mask rather than just making it affordable. |
|
This one will require some more work I guess. I should have a Polaris card to try, I just need a spare machine for these tests. Give me a few more days and I'll report back. |
55919ca to
f65bd23
Compare
|
I've rebased this on master and pushed a fix. The descriptor pools now grow when needed, and allocation failures stop the frame before submission instead of leaving it partially rendered. I also adjusted the SHAPE clipping for the updated renderer. Tests and Clippy pass, including software Vulkan tests with over 4,000 draws and simulated allocation failures. I haven't reproduced the RX580 crash, though, so I can't say yet whether this fixes what you were seeing. |
Rebase the descendant Bounding fix onto the current visibility/border walker. Keep exact ancestor winSize constraints separate from capped occlusion regions, including empty regions and Clip shapes, and normalize at the backend boundary. Grow only free per-output descriptor pools to full frame demand. Allocate sets as one batch and propagate allocation failures before recording/submission; never submit a truncated scene. Replace pools whose reset failed before reuse. Add headless pixel, alpha, pool-lifetime and allocation-error regressions. Validation: nightly fmt, exact CI Clippy on Rust 1.98.0, 2871 default tests, and focused Lavapipe tests with Khronos validation. RX580 crash not reproduced; no hardware qualification claimed.
f65bd23 to
c5b8840
Compare
|
Hi, thx for updating, but I can no longer repro the white boxes on plasma, not with and not without compositor on current master. Are you able to? |
|
I went back to the commit this PR originally started from and built a synthetic test for the shaped panel and its unshaped child. The old version reproduces the white margin, but current master handles it correctly. That matches what you're seeing. There is still a clipping issue with more complex shapes. With intersecting parent/child stripe masks, master paints 4,160 pixels outside the mask; the PR preserves the gaps correctly. These are synthetic renders using Lavapipe, not Plasma screenshots. Each revision builds its own draw list, which I replayed through the same recorder and checked pixel by pixel. So the original panel case appears covered by master now. I think this PR is still useful for complex shapes and descriptor-pool handling, but I should update its description to reflect that. |


Why
The SHAPE Bounding region applies to a window and its inferiors. The KMS
scene walk already accumulated ancestor geometry for parent clipping, but it
did not accumulate ancestor Bounding regions. A shaped parent therefore
clipped its own draw while an unshaped descendant could still paint outside
that shape.
This was visible on non-composited Plasma 6.6 on amdgpu/Strix Halo. KWin
shapes the panel frame into a rounded three-rectangle band inside a
3440x40frame, but the unshaped full-height wrapper child was emitted infull. Its background painted an opaque white band over the panel margin.
Enabling compositing hid the bug because KWin then sampled the shaped window
as a texture and the cut-out was carried by alpha.
The first extents-based attempt also demonstrated why preserving the exact
region matters: it left the four bounding-box corner pixels painted even
though they were outside the rounded mask.
What changed
emit_window_subtreeas absolute half-open rectangles.NoneversusSome([])distinction: no shaped ancestor isdifferent from an explicitly empty intersection that suppresses the
subtree.
regions are sorted, non-overlapping YX bands. This also prevents
overlapping client rectangles from becoming overlapping SrcOver draws in
a COW subtree.
canonical result once per emitted window.
exceed 64 rectangles, and vertical stripes intersecting horizontal stripes
can inherently produce the Cartesian product as disjoint output. Replacing
that exact result with its extents violates SHAPE by painting holes.
a candidate
Vec, and a shaped leaf with no shaped ancestor does not buildan unused absolute-region copy.
sampled_idsand presentation-damage snapshots once per window evenwhen one shape produces multiple draws.
Validation
The original panel case was verified on hardware, including the four
bounding-box corner pixels of the rounded mask. The review follow-ups add
regressions for:
All repository gates pass:
cargo +nightly fmtcargo clippy --all-targets -- -D warningscargo test --workspace