Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DrmOutputManager doesn't work on Apple Silicon (M2) #1661

Open
kenoss opened this issue Feb 24, 2025 · 7 comments · May be fixed by #1662
Open

DrmOutputManager doesn't work on Apple Silicon (M2) #1661

kenoss opened this issue Feb 24, 2025 · 7 comments · May be fixed by #1662

Comments

@kenoss
Copy link
Contributor

kenoss commented Feb 24, 2025

Context

I'm updating smithay in my Wayland compositor sabiniwm.
I forked it from anvil and it shares the basic structure with anvil, especially udev.rs.
In this work, I found that a corresponding commit of smithay 4deb3d5 works on a machine with an NVIDIA GPU but doesn't on Apple Silicon (M2).

The branch is archive/smithay-4deb3d5-doesnt-work-on-apple-silicon.
There are two commits corresponding to smithay 4deb3d5 (for backend updates 5186cf7..71dc1c5).

  • dfb0f8f: Necessary update. It works on both NVIDIA and M2.
  • 414f98f: Use DrmOutputManager in favor of SurfaceComposition. It works on NVIDIA but doesn't on M2.

An crash occurs here if we use initial_render.

Log on dfb0f8f (Precisely speaking, 5c86480 with smithay with warn!()s):

...(snip)...
03:00:37.437  INFO drm_atomic:create_surface{crtc=crtc::Handle(33) mode=Mode { name: "2560x1600", clock: 277042, size: (2560, 1600), hsync: (2568, 2600, 2640), vsync: (1633, 170
5, 1749), hskew: 0, vscan: 0, vrefresh: 60, mode_type: ModeTypeFlags(PREFERRED | DRIVER) } connectors=[connector::Handle(35)]}:drm_atomic{crtc=crtc::Handle(33)}: smithay::backen
d::drm::surface::atomic: 186: Initializing drm surface (crtc::Handle(33):plane::Handle(31)) with mode Mode { name: "2560x1600", clock: 277042, size: (2560, 1600), hsync: (2568,
2600, 2640), vsync: (1633, 1705, 1749), hskew: 0, vscan: 0, vrefresh: 60, mode_type: ModeTypeFlags(PREFERRED | DRIVER) } and connectors [connector::Handle(35)]
03:00:37.437  WARN new: smithay::backend::drm::compositor: 1116: new(), /home/kenoss/src/github.com/Smithay/smithay/src/backend/drm/compositor/mod.rs:1116
03:00:37.437  WARN new: smithay::backend::drm::compositor: 1131: failed to create signaled syncobj err=Os { code: 95, kind: Uncategorized, message: "Operation not supported" }
03:00:37.438  WARN new: smithay::backend::drm::compositor: 1264: Preferred format AB30 not available: NoSupportedPlaneFormat
03:00:37.439  WARN smithay::backend::drm::compositor: 2718: set_debug_flags(), /home/kenoss/src/github.com/Smithay/smithay/src/backend/drm/compositor/mod.rs:2718
03:00:37.443  WARN sabiniwm::backend::udev: 1567: initial_render(), crates/sabiniwm/src/backend/udev.rs:1567
03:00:37.443  WARN smithay::backend::drm::compositor: 1667: render_frame(), /home/kenoss/src/github.com/Smithay/smithay/src/backend/drm/compositor/mod.rs:1667
03:00:37.444  WARN sabiniwm::backend::udev: 1578: initial_render(), render_frame(), ok, x = SurfaceCompositorRenderResult { rendered: true, states: RenderElementStates { states: {} }, sync: None, damage: None }, rendered = true
03:00:37.444  WARN smithay::backend::drm::compositor: 2404: queue_frame(), /home/kenoss/src/github.com/Smithay/smithay/src/backend/drm/compositor/mod.rs:2404
03:00:37.445  WARN smithay::backend::drm::compositor: 2494: submit(), /home/kenoss/src/github.com/Smithay/smithay/src/backend/drm/compositor/mod.rs:2494
03:00:37.445  INFO smithay::backend::drm::surface::atomic: 749: Adding connector: EmbeddedDisplayPort
03:00:37.445  INFO smithay::backend::drm::surface::atomic: 756: Setting new mode: "2560x1600"
03:00:37.445  WARN smithay::backend::drm::surface::atomic: 781: Failed to destroy old mode property blob: No such file or directory (os error 2)
03:00:37.493  WARN smithay::backend::drm::compositor: 2521: handle_flip(), /home/kenoss/src/github.com/Smithay/smithay/src/backend/drm/compositor/mod.rs:2521
03:00:37.493  WARN sabiniwm::backend::udev: 1588: initial_render(), queue_frame(), ok
03:00:37.493  WARN smithay::backend::drm::compositor: 2587: reset_buffers(), /home/kenoss/src/github.com/Smithay/smithay/src/backend/drm/compositor/mod.rs:2587
03:00:37.493  INFO sabiniwm::backend::udev: 261: Trying to initialize EGL Hardware Acceleration self.selected_render_node=DrmNode { dev: 57984, ty: Render }
03:00:37.493  INFO sabiniwm::backend::udev: 266: EGL hardware-acceleration enabled
...(snip)...

Log on 414f98f:

...(snip)...
03:02:34.709  INFO drm_atomic:create_surface{crtc=crtc::Handle(33) mode=Mode { name: "2560x1600", clock: 277042, size: (2560, 1600), hsync: (2568, 2600, 2640), vsync: (1633, 170
5, 1749), hskew: 0, vscan: 0, vrefresh: 60, mode_type: ModeTypeFlags(PREFERRED | DRIVER) } connectors=[connector::Handle(35)]}:drm_atomic{crtc=crtc::Handle(33)}: smithay::backend::drm::surface::atomic: 186: Initializing drm surface (crtc::Handle(33):plane::Handle(31)) with mode Mode { name: "2560x1600", clock: 277042, size: (2560, 1600), hsync: (2568, 2600, 2640), vsync: (1633, 1705, 1749), hskew: 0, vscan: 0, vrefresh: 60, mode_type: ModeTypeFlags(PREFERRED | DRIVER) } and connectors [connector::Handle(35)]
03:02:34.709  WARN new: smithay::backend::drm::compositor: 1116: new(), /home/kenoss/src/github.com/Smithay/smithay/src/backend/drm/compositor/mod.rs:1116
03:02:34.709  WARN new: smithay::backend::drm::compositor: 1131: failed to create signaled syncobj err=Os { code: 95, kind: Uncategorized, message: "Operation not supported" }
03:02:34.710  WARN new: smithay::backend::drm::compositor: 1264: Preferred format AB30 not available: NoSupportedPlaneFormat
03:02:34.711  WARN smithay::backend::drm::compositor: 1667: render_frame(), /home/kenoss/src/github.com/Smithay/smithay/src/backend/drm/compositor/mod.rs:1667
03:02:34.713  WARN smithay::backend::drm::compositor: 2439: commit_frame(), /home/kenoss/src/github.com/Smithay/smithay/src/backend/drm/compositor/mod.rs:2439
03:02:34.713  INFO smithay::backend::drm::surface::atomic: 749: Adding connector: EmbeddedDisplayPort
03:02:34.713  INFO smithay::backend::drm::surface::atomic: 756: Setting new mode: "2560x1600"
03:02:34.713  WARN smithay::backend::drm::surface::atomic: 781: Failed to destroy old mode property blob: No such file or directory (os error 2)
03:02:34.765  WARN smithay::backend::drm::compositor: 2521: handle_flip(), /home/kenoss/src/github.com/Smithay/smithay/src/backend/drm/compositor/mod.rs:2521
03:02:34.765  WARN smithay::backend::drm::compositor: 2718: set_debug_flags(), /home/kenoss/src/github.com/Smithay/smithay/src/backend/drm/compositor/mod.rs:2718
03:02:34.770  WARN sabiniwm::backend::udev: 1417: initial_render(), crates/sabiniwm/src/backend/udev.rs:1417
03:02:34.770  WARN smithay::backend::drm::compositor: 1667: render_frame(), /home/kenoss/src/github.com/Smithay/smithay/src/backend/drm/compositor/mod.rs:1667
03:02:34.771  WARN sabiniwm::backend::udev: 1428: initial_render(), render_frame(), ok, x = RenderFrameResult { is_empty: false, states: RenderElementStates { states: {} }, primary_element: Swapchain(PrimarySwapchainElement { slot: DrmScanoutBuffer { buffer: Swapchain(Slot(InternalSlot { buffer: Some(GbmBuffer { bo: BufferObject { ptr: 0xaaab83034910, device: 0xaaab830347c0, width: 2560, height: 1600, offsets: [0, 0, 0, 0], stride: 10240, format: DrmFourcc(AR30), modifier: Linear }, size: Size<smithay::utils::geometry::Buffer> { w: 2560, h: 1600 }, format: DrmFormat { code: DrmFourcc(AR30), modifier: Linear } }), acquired: true, age: 1, userdata: UserDataMap { list: AppendList(0xaaab8301e2f0) } })), fb: CachedDrmFramebuffer(Exporter(GbmFramebuffer { fb: framebuffer::Handle(38), format: DrmFormat { code: DrmFourcc(XR30), modifier: Linear }, drm: DrmDeviceFd(InternalDrmDeviceFd { fd: DeviceFd(OwnedFd { fd: 26 }), privileged: false }) })) }, sync: SyncPoint { fence: Some(EGLFence(InnerEGLFence { display_handle: EGLDisplayHandle { handle: 0xaaab827fc5b0, should_terminate: true, _native: Any { .. } }, handle: 0xaaab828006f0, native: true })) }, transform: Normal, damage: DamageSnapshot { commit_counter: CommitCounter(2), damage: [[Rectangle<smithay::utils::geometry::Buffer> { x: 0, y: 0, width: 2560, height: 1600 }], [Rectangle<smithay::utils::geometry::Buffer> { x: 0, y: 0, width: 2560, height: 1600 }]] } }), overlay_elements: [], cursor_element: None }, rendered = true
03:02:34.771  WARN smithay::backend::drm::compositor: 2404: queue_frame(), /home/kenoss/src/github.com/Smithay/smithay/src/backend/drm/compositor/mod.rs:2404
03:02:34.771  WARN smithay::backend::drm::compositor: 2494: submit(), /home/kenoss/src/github.com/Smithay/smithay/src/backend/drm/compositor/mod.rs:2494
03:02:34.771  WARN smithay::backend::drm::compositor: 2521: handle_flip(), /home/kenoss/src/github.com/Smithay/smithay/src/backend/drm/compositor/mod.rs:2521
03:02:34.771  WARN sabiniwm::backend::udev: 1450: initial_render(), queue_frame(), e = DrmError(Access(AccessError { errmsg: "Page flip commit failed", dev: Some("/dev/dri/card2"), source: Os { code: 16, kind: ResourceBusy, message: "Device or resource busy" } }))
03:02:35.444 ERROR sabiniwm::util::panic: 23: panic hook: thread "main" panicked
backtrace:
   0: sabiniwm::util::panic::set_hook::{{closure}}
             at src/github.com/kenoss/sabiniwm/crates/sabiniwm/src/util/panic.rs:30:39
   1: <alloc::boxed::Box<F,A> as core::ops::function::Fn<Args>>::call
             at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/alloc/src/boxed.rs:2245:9
      std::panicking::rust_panic_with_hook
             at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/std/src/panicking.rs:805:13
   2: std::panicking::begin_panic_handler::{{closure}}
             at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/std/src/panicking.rs:671:13
   3: std::sys::backtrace::__rust_end_short_backtrace
             at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/std/src/sys/backtrace.rs:170:18
   4: rust_begin_unwind
             at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/std/src/panicking.rs:662:5
   5: core::panicking::panic_fmt
             at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/core/src/panicking.rs:74:14
   6: sabiniwm::backend::udev::<impl sabiniwm::state::SabiniwmStateWithConcreteBackend<sabiniwm::backend::udev::UdevBackend>>::schedule_initial_render
             at src/github.com/kenoss/sabiniwm/crates/sabiniwm/src/backend/udev.rs:1244:55
   7: sabiniwm::backend::udev::<impl sabiniwm::state::SabiniwmStateWithConcreteBackend<sabiniwm::backend::udev::UdevBackend>>::connector_connected::{{closure}}
             at src/github.com/kenoss/sabiniwm/crates/sabiniwm/src/backend/udev.rs:841:17
   8: sabiniwm::backend::udev::<impl sabiniwm::state::SabiniwmStateWithConcreteBackend<sabiniwm::backend::udev::UdevBackend>>::connector_connected
             at src/github.com/kenoss/sabiniwm/crates/sabiniwm/src/backend/udev.rs:847:15
   9: sabiniwm::backend::udev::<impl sabiniwm::state::SabiniwmStateWithConcreteBackend<sabiniwm::backend::udev::UdevBackend>>::device_changed
             at src/github.com/kenoss/sabiniwm/crates/sabiniwm/src/backend/udev.rs:915:25
  10: sabiniwm::backend::udev::<impl sabiniwm::state::SabiniwmStateWithConcreteBackend<sabiniwm::backend::udev::UdevBackend>>::device_added
             at src/github.com/kenoss/sabiniwm/crates/sabiniwm/src/backend/udev.rs:667:9
  11: <sabiniwm::backend::udev::UdevBackend as sabiniwm::backend::BackendI>::init::{{closure}}
             at src/github.com/kenoss/sabiniwm/crates/sabiniwm/src/backend/udev.rs:238:21
  12: core::result::Result<T,E>::and_then
             at /rustc/f6e511eec7342f59a25f7c0534f1dbea00d01b14/library/core/src/result.rs:1346:22
  13: <sabiniwm::backend::udev::UdevBackend as sabiniwm::backend::BackendI>::init
             at src/github.com/kenoss/sabiniwm/crates/sabiniwm/src/backend/udev.rs:231:31
  14: <sabiniwm::backend::Backend as sabiniwm::backend::BackendI>::init
             at src/github.com/kenoss/sabiniwm/crates/sabiniwm/src/backend/mod.rs:19:8
  15: sabiniwm::state::SabiniwmState::run
             at src/github.com/kenoss/sabiniwm/crates/sabiniwm/src/state.rs:167:9
  16: sabiniwm_pistachio::main
             at src/github.com/kenoss/sabiniwm/crates/sabiniwm-pistachio/src/main.rs:231:5
...(snip)...

I found that DrmOutputBuilder::build() calls. DrmCompositor::commit_frame().
Removing the call makes it works (not calling render_frame() doesn't affect the behavior):

diff --git a/src/backend/drm/output.rs b/src/backend/drm/output.rs
index d3b633f94..b080a0acb 100644
--- a/src/backend/drm/output.rs
+++ b/src/backend/drm/output.rs
@@ -404,7 +404,7 @@ where
         compositor
             .render_frame(renderer, elements, *clear_color, FrameMode::COMPOSITE)
             .map_err(DrmOutputManagerError::RenderFrame)?;
-        compositor.commit_frame().map_err(DrmOutputManagerError::Frame)?;
+        // compositor.commit_frame().map_err(DrmOutputManagerError::Frame)?;

         Ok(DrmOutput {
             crtc: self.crtc,

Environment

Machine with NVIDIA, Arch Linux

$ uname -a
Linux tataricus 6.9.9-arch1-1 #1 SMP PREEMPT_DYNAMIC Fri, 12 Jul 2024 00:06:53 +0000 x86_64 GNU/Linux

$ inxi -G
Graphics:
  Device-1: NVIDIA GP107 [GeForce GTX 1050 Ti] driver: nouveau v: kernel
  Display: server: X.org v: 1.21.1.13 with: Xwayland v: 24.1.4 driver: N/A
    resolution: <missing: xdpyinfo/xrandr>
  API: OpenGL Message: Unable to show GL data. glxinfo is missing.
  Info: Tools: x11: xprop

M2 Mac Book Air, Asahi Linux

$ uname -a
Linux keno-asahi 6.9.11-400.asahi.fc40.aarch64+16k #1 SMP PREEMPT_DYNAMIC Fri Jul 26 14:07:41 UTC 2024 aarch64 GNU/Linux

$ inxi -G
Graphics:
  Device-1: agx-t8112 driver: asahi v: kernel
  Device-2: display-subsystem driver: apple_drm v: N/A
  Device-3: h7-display-pipe driver: N/A
  Display: wayland server: X.org v: 1.20.14 with: Xwayland v: 24.1.1 driver:
    X: loaded: modesetting dri: apple gpu: apple-drm
  API: OpenGL Message: No GL data available.
  API: EGL Message: EGL data requires eglinfo. Check --recommends.
  Info: Tools: api: glxinfo wl: wlr-randr x11: xdriinfo, xdpyinfo, xprop,
    xrandr

Questions and proposition

  • Q1. What is the intention of render_frame() and commit_frame() calls? As the calls don't affect the behavior (AFAICS), I propose to remove them.
  • (Q2. Is this a bug of driver of Asahi Linux?)

WDYT?


Note that I tried to reproduce it with anvil, not using sabiniwm, but it crashes and looks not easy. Sorry.

@cmeissl
Copy link
Collaborator

cmeissl commented Feb 25, 2025

Q1. What is the intention of render_frame() and commit_frame() calls? As the calls don't affect the behavior (AFAICS), I propose to remove them.

commit_frame is used to make sure the framebuffer is actually committed instead of just queuing the framebuffer. You can read about the reason for this in #1576 and the linked comment. tldr is it tries to solve bandwidth issues with multiple active outputs.

So no, commit_frame is called intentionally here and can not be removed.


Where exactly does the panic happen? I can not directly correlate the panic to the source here: https://github.com/kenoss/sabiniwm/blob/archive/smithay-4deb3d5-doesnt-work-on-apple-silicon/crates/sabiniwm/src/backend/udev.rs#L1244
Does it panic in SwapBuffersError::ContextLost(err) => panic!("Rendering loop lost: {}", err),?

From the log it looks like the drm device returns a device or resource busy error. Possible that we do not handle that at the moment. The temporary error is evaluated here:

ErrorKind::PermissionDenied | ErrorKind::WouldBlock | ErrorKind::Interrupted
and iirc we would expect WouldBlock in this case. Unfortunately https://doc.rust-lang.org/std/io/enum.ErrorKind.html#variant.ResourceBusy is only available since 1.83 which is higher than our MSRV. So we could try to use https://doc.rust-lang.org/std/io/struct.Error.html#method.raw_os_error and match on the raw code for now.

You could either try to patch smithay to handle the error with https://doc.rust-lang.org/std/io/struct.Error.html#method.raw_os_error or for a quick test do something similar with inspecting the error by downcasting it in you SwapBuffersError::ContextLost handling.


(Possible that the driver needs some time for the commit and declines drm operations until it is finished)

@Drakulix
Copy link
Member

Unfortunately https://doc.rust-lang.org/std/io/enum.ErrorKind.html#variant.ResourceBusy is only available since 1.83 which is higher than our MSRV.

Any chance we could bump the MSRV @cmeissl ?

@cmeissl
Copy link
Collaborator

cmeissl commented Feb 25, 2025

Unfortunately https://doc.rust-lang.org/std/io/enum.ErrorKind.html#variant.ResourceBusy is only available since 1.83 which is higher than our MSRV.

Any chance we could bump the MSRV @cmeissl ?

I just finished bumping our toolchain to 1.81.0, which is the most recent version available in yocto for us at the moment. Something like 1.83 or newer will probably take a few months to show up.

@Drakulix
Copy link
Member

Then we probably should do a workaround with raw_os_error.

@cmeissl
Copy link
Collaborator

cmeissl commented Feb 25, 2025

Then we probably should do a workaround with raw_os_error.

I can prepare something tomorrow latest, maybe already a bit later today.

@cmeissl
Copy link
Collaborator

cmeissl commented Feb 25, 2025

We already depend on rustix, which provides both. A function to get a errno from an std IO error and a definition for EBUSY. So this should be easyly doable. Will open a PR a bit later.

@cmeissl cmeissl linked a pull request Feb 25, 2025 that will close this issue
@Drakulix
Copy link
Member

@kenoss Can you test if #1662 solves your problem?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants