Skip to content

perf(plugins/servo): zero-copy Servo → compositor via DMA-BUF texture sharing #349

@staging-devin-ai-integration

Description

Summary

Eliminate the CPU readback in the Servo → compositor path by sharing GPU textures via Linux DMA-BUF. Currently, every frame goes through SoftwareRenderingContext::read_to_image() which copies pixel data from the CPU-side llvmpipe buffer into a Vec<u8>, then the compositor uploads it to a wgpu texture. With DMA-BUF, Servo's GL framebuffer can be exported as a file descriptor and imported directly by wgpu as a texture — zero CPU pixel copies.

Parent issue: #167
Depends on: #323 (PoC — merged)
Blocked by: Nothing (can start independently)

Architecture

Current path (CPU readback):
  Servo (llvmpipe GL) → glReadPixels → Vec<u8> → wgpu::Queue::write_texture → compositor

Proposed path (DMA-BUF zero-copy):
  Servo (EGL/GL) → eglExportDMABUFImageMESA → DMA-BUF fd
    → wgpu-hal import (VkImage from fd) → compositor texture layer

Key EGL extensions

  • EGL_MESA_image_dma_buf_export — export an EGLImage to a DMA-BUF fd + fourcc + stride
  • EGL_EXT_image_dma_buf_import — import a DMA-BUF fd as an EGLImage (wgpu side)

Prerequisites

  • Servo must use a hardware RenderingContext (EGL-based, not SoftwareRenderingContext)
  • The system must have a GPU with DMA-BUF support (most Mesa drivers, NVIDIA 515+)
  • wgpu must be using a Vulkan backend (for VkImportMemoryFdInfoKHR)

Implementation Steps

  1. Switch Servo to EGL rendering context — replace SoftwareRenderingContext with a hardware EGL context (e.g. via surfaceless EGL or GBM platform). This requires Servo to render on a real GPU.

  2. Export GL FBO as DMA-BUF — after webview.paint(), use eglExportDMABUFImageMESA to get the fd, fourcc, stride, and offset of the rendered frame.

  3. Import DMA-BUF into wgpu — use wgpu-hal's unsafe Vulkan API to import the DMA-BUF fd as a VkImage via VkImportMemoryFdInfoKHR, then wrap it as a wgpu::Texture.

  4. GL↔Vulkan synchronization — use EGL_KHR_fence_sync / VkSemaphore with fd export/import to ensure the GL render is complete before Vulkan reads the texture.

  5. Fallback path — if DMA-BUF extensions are unavailable (e.g. in CI, headless without GPU), fall back to the existing CPU readback path.

Acceptance Criteria

  • Servo uses a hardware EGL rendering context (when GPU is available)
  • GL framebuffer exported as DMA-BUF fd via EGL extension
  • wgpu imports DMA-BUF fd as a wgpu::Texture via wgpu-hal unsafe API
  • Compositor uses the imported texture directly as a layer input (no CPU copy)
  • Proper GL↔Vulkan synchronization (fence-based)
  • Fallback to CPU readback path if DMA-BUF extensions are unavailable
  • Feature-gated behind servo-gpu or similar (Linux-only)
  • Benchmark: measure per-frame latency and CPU usage reduction vs. CPU readback

Complexity

Effort: L (1–2 weeks)
Involves EGL extension plumbing, wgpu-hal unsafe API, cross-API synchronization, and proper fallback logic.

References

  • bits-craft/wgpu-dma-buf — reference implementation for DMA-BUF → wgpu import
  • EGL_MESA_image_dma_buf_export specification
  • EGL_EXT_image_dma_buf_import specification
  • VK_KHR_external_memory_fd — Vulkan extension for importing DMA-BUF memory

Notes

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions