refactor(drm): mark the Vulkan-export output image fallback deprecated
Comment exportImages and its setupImages branch as a deprecated fallback tracked by neferwl#23, and log the zero-copy output line as a warning when it is used so reports show it.
2 files · +13 -2
M docs/dev/architecture.md +1 -1
| @@ -29,7 +29,7 @@ About 35 channels connect them, all created in one place, so the full data flow | |||
| 29 | 29 | A DRM output flips between two images the renderer draws into, with no CPU copy. | |
| 30 | 30 | ||
| 31 | 31 | - **Allocation:** the images are allocated with GBM (`GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING`), with the modifiers the primary plane lists that the renderer can render into and import. The renderer imports them as Vulkan images, and KMS gets framebuffers made from the same dmabufs. GBM is the display driver's own allocator, so the layouts it picks scan out correctly on every driver. | |
| 32 | - | - **Fallback:** when libgbm is missing, GBM allocates nothing usable, or Vulkan or KMS refuses the images, the renderer allocates and exports them itself. Each kind (driver modifier, single-plane, linear) tries GBM, then the renderer. The log line `zero-copy output` names the allocator in its `alloc` field (`gbm` or `vulkan`). | |
| 32 | + | - **Fallback:** when libgbm is missing, GBM allocates nothing usable, or Vulkan or KMS refuses the images, the renderer allocates and exports them itself. Each kind (driver modifier, single-plane, linear) tries GBM, then the renderer. The log line `zero-copy output` names the allocator in its `alloc` field (`gbm` or `vulkan`), and is a warning for `vulkan`. This fallback is deprecated and goes away once GBM is validated on more setups (neferwl#23). | |
| 33 | 33 | - **Sync:** nvidia-drm before 560.35.3 does not wait for `IN_FENCE_FD`. On it, the output waits for each frame's fence on the CPU and commits without one. A client buffer whose fence is still pending is composed, not scanned out, while `IN_FENCE_FD` is unavailable. | |
| 34 | 34 | ||
| 35 | 35 | I also like bringing more tools to the Go ecosystem. NeferWL grew its own libraries along the way, and other Go projects can use them: | |
| @@ -29,7 +29,7 @@ About 35 channels connect them, all created in one place, so the full data flow | |||||
| 29 | A DRM output flips between two images the renderer draws into, with no CPU copy. | 29 | A DRM output flips between two images the renderer draws into, with no CPU copy. | ||
| 30 | 30 | ||||
| 31 | - **Allocation:** the images are allocated with GBM (`GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING`), with the modifiers the primary plane lists that the renderer can render into and import. The renderer imports them as Vulkan images, and KMS gets framebuffers made from the same dmabufs. GBM is the display driver's own allocator, so the layouts it picks scan out correctly on every driver. | 31 | - **Allocation:** the images are allocated with GBM (`GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING`), with the modifiers the primary plane lists that the renderer can render into and import. The renderer imports them as Vulkan images, and KMS gets framebuffers made from the same dmabufs. GBM is the display driver's own allocator, so the layouts it picks scan out correctly on every driver. | ||
| 32 | - | - **Fallback:** when libgbm is missing, GBM allocates nothing usable, or Vulkan or KMS refuses the images, the renderer allocates and exports them itself. Each kind (driver modifier, single-plane, linear) tries GBM, then the renderer. The log line `zero-copy output` names the allocator in its `alloc` field (`gbm` or `vulkan`). | 32 | + | - **Fallback:** when libgbm is missing, GBM allocates nothing usable, or Vulkan or KMS refuses the images, the renderer allocates and exports them itself. Each kind (driver modifier, single-plane, linear) tries GBM, then the renderer. The log line `zero-copy output` names the allocator in its `alloc` field (`gbm` or `vulkan`), and is a warning for `vulkan`. This fallback is deprecated and goes away once GBM is validated on more setups (neferwl#23). |
| 33 | - **Sync:** nvidia-drm before 560.35.3 does not wait for `IN_FENCE_FD`. On it, the output waits for each frame's fence on the CPU and commits without one. A client buffer whose fence is still pending is composed, not scanned out, while `IN_FENCE_FD` is unavailable. | 33 | - **Sync:** nvidia-drm before 560.35.3 does not wait for `IN_FENCE_FD`. On it, the output waits for each frame's fence on the CPU and commits without one. A client buffer whose fence is still pending is composed, not scanned out, while `IN_FENCE_FD` is unavailable. | ||
| 34 | 34 | ||||
| 35 | I also like bringing more tools to the Go ecosystem. NeferWL grew its own libraries along the way, and other Go projects can use them: | 35 | I also like bringing more tools to the Go ecosystem. NeferWL grew its own libraries along the way, and other Go projects can use them: | ||
M internal/adapters/drm/images.go +12 -1
| @@ -193,6 +193,9 @@ func (o *Output) setupImages(r ports.Renderer, kind imageKind, cause error, skip | |||
| 193 | 193 | } | |
| 194 | 194 | o.log.Info().Err(gerr).Str("connector", o.conn.name).Int("kind", int(kind)).Str("alloc", allocGBM).Msg("output image allocation") | |
| 195 | 195 | } | |
| 196 | + | // Deprecated fallback (neferwl#23): renderer-exported images, kept | |
| 197 | + | // while GBM is validated on few setups. Remove once no report shows | |
| 198 | + | // "alloc":"vulkan" for a few releases. | |
| 196 | 199 | if err = o.exportImages(r, mods, kind == imagesSinglePlane); err == nil { | |
| 197 | 200 | return kind, nil | |
| 198 | 201 | } | |
| @@ -232,6 +235,9 @@ func closeBufs(bufs []ports.DMABuf) { | |||
| 232 | 235 | } | |
| 233 | 236 | ||
| 234 | 237 | // exportImages makes the renderer's exported targets the output images. | |
| 238 | + | // | |
| 239 | + | // Deprecated fallback for gbmImages, to remove with neferwl#23. Exported | |
| 240 | + | // Vulkan images corrupt scanout on nvidia-drm. | |
| 235 | 241 | func (o *Output) exportImages(r ports.Renderer, mods []uint64, singlePlane bool) error { | |
| 236 | 242 | o.dropImages(r) | |
| 237 | 243 | bufs, err := r.ExportTargets(len(o.fbs), mods, singlePlane) | |
| @@ -266,7 +272,12 @@ func (o *Output) showBufs(r ports.Renderer, bufs []ports.DMABuf, alloc string) e | |||
| 266 | 272 | return err | |
| 267 | 273 | } | |
| 268 | 274 | o.planes, o.imageMod = len(bufs[0].Planes), bufs[0].Modifier | |
| 269 | - | o.log.Info().Str("connector", o.conn.name).Uint64("modifier", bufs[0].Modifier).Int("planes", o.planes).Str("alloc", alloc).Msg("zero-copy output") | |
| 275 | + | ev := o.log.Info() | |
| 276 | + | if alloc == allocVulkan { | |
| 277 | + | // The deprecated fallback is in use: make it visible in reports. | |
| 278 | + | ev = o.log.Warn() | |
| 279 | + | } | |
| 280 | + | ev.Str("connector", o.conn.name).Uint64("modifier", bufs[0].Modifier).Int("planes", o.planes).Str("alloc", alloc).Msg("zero-copy output") | |
| 270 | 281 | return nil | |
| 271 | 282 | } | |
| 272 | 283 | ||
| @@ -193,6 +193,9 @@ func (o *Output) setupImages(r ports.Renderer, kind imageKind, cause error, skip | |||||
| 193 | } | 193 | } | ||
| 194 | o.log.Info().Err(gerr).Str("connector", o.conn.name).Int("kind", int(kind)).Str("alloc", allocGBM).Msg("output image allocation") | 194 | o.log.Info().Err(gerr).Str("connector", o.conn.name).Int("kind", int(kind)).Str("alloc", allocGBM).Msg("output image allocation") | ||
| 195 | } | 195 | } | ||
| 196 | + | // Deprecated fallback (neferwl#23): renderer-exported images, kept | |||
| 197 | + | // while GBM is validated on few setups. Remove once no report shows | |||
| 198 | + | // "alloc":"vulkan" for a few releases. | |||
| 196 | if err = o.exportImages(r, mods, kind == imagesSinglePlane); err == nil { | 199 | if err = o.exportImages(r, mods, kind == imagesSinglePlane); err == nil { | ||
| 197 | return kind, nil | 200 | return kind, nil | ||
| 198 | } | 201 | } | ||
| @@ -232,6 +235,9 @@ func closeBufs(bufs []ports.DMABuf) { | |||||
| 232 | } | 235 | } | ||
| 233 | 236 | ||||
| 234 | // exportImages makes the renderer's exported targets the output images. | 237 | // exportImages makes the renderer's exported targets the output images. | ||
| 238 | + | // | |||
| 239 | + | // Deprecated fallback for gbmImages, to remove with neferwl#23. Exported | |||
| 240 | + | // Vulkan images corrupt scanout on nvidia-drm. | |||
| 235 | func (o *Output) exportImages(r ports.Renderer, mods []uint64, singlePlane bool) error { | 241 | func (o *Output) exportImages(r ports.Renderer, mods []uint64, singlePlane bool) error { | ||
| 236 | o.dropImages(r) | 242 | o.dropImages(r) | ||
| 237 | bufs, err := r.ExportTargets(len(o.fbs), mods, singlePlane) | 243 | bufs, err := r.ExportTargets(len(o.fbs), mods, singlePlane) | ||
| @@ -266,7 +272,12 @@ func (o *Output) showBufs(r ports.Renderer, bufs []ports.DMABuf, alloc string) e | |||||
| 266 | return err | 272 | return err | ||
| 267 | } | 273 | } | ||
| 268 | o.planes, o.imageMod = len(bufs[0].Planes), bufs[0].Modifier | 274 | o.planes, o.imageMod = len(bufs[0].Planes), bufs[0].Modifier | ||
| 269 | - | o.log.Info().Str("connector", o.conn.name).Uint64("modifier", bufs[0].Modifier).Int("planes", o.planes).Str("alloc", alloc).Msg("zero-copy output") | 275 | + | ev := o.log.Info() |
| 276 | + | if alloc == allocVulkan { | |||
| 277 | + | // The deprecated fallback is in use: make it visible in reports. | |||
| 278 | + | ev = o.log.Warn() | |||
| 279 | + | } | |||
| 280 | + | ev.Str("connector", o.conn.name).Uint64("modifier", bufs[0].Modifier).Int("planes", o.planes).Str("alloc", alloc).Msg("zero-copy output") | |||
| 270 | return nil | 281 | return nil | ||
| 271 | } | 282 | } | ||
| 272 | 283 | ||||