DMA-BUF Backend
The Linux backend uses DMA-BUF for cross-process GPU texture sharing via GBM and EGL.
Overview
DMA-BUF is a Linux kernel feature for sharing buffers between devices and processes. Nozzle uses GBM (Generic Buffer Manager) to allocate DMA-BUF buffers and EGL to create GPU textures from them.
How It Works
Sender Process Receiver Process
───────────────── ─────────────────
GBM Device GBM Device
│ │
├── Allocate DMA-BUF via GBM │
├── Create EGLImage from DMA-BUF │
├── Render into texture │
├── Publish DMA-BUF fd │
│ via shared state │
│ ├── Receive DMA-BUF fd
│ ├── Create EGLImage
│ ├── Read texture
│ │
└── Ring buffer (N buffers) └── Frame acquisition
Thread Safety
Synchronization is managed through the shared state ring buffer with atomic counters. DMA-BUF file descriptors are duplicated between processes.
Zero-Copy
Texture data stays in GPU-accessible memory. DMA-BUF file descriptors allow both processes to reference the same buffer without copying. Transfer mode is zero_copy_shared_texture.
Backend API
#include <nozzle/backends/linux.hpp>
namespace nozzle::dma_buf {
Result<device> wrap_device(const device_desc &desc);
Result<texture> wrap_texture(const texture_wrap_desc &desc);
void *get_egl_image(const texture &tex);
int get_dmabuf_fd(const texture &tex);
}
device_desc
struct device_desc {
void *gbm_device{nullptr}; // struct gbm_device *
};
texture_wrap_desc
struct texture_wrap_desc {
void *egl_image{nullptr}; // EGLImage
int dmabuf_fd{-1}; // DMA-BUF file descriptor
uint32_t fourcc{0}; // DRM fourcc code
uint32_t stride{0}; // Row stride in bytes
uint64_t modifier{0}; // DRM format modifier
uint32_t width{0};
uint32_t height{0};
};
wrap_device
Wrap an existing GBM device.
Result<device> wrap_device(const device_desc &desc);
auto dev = nozzle::dma_buf::wrap_device({
.gbm_device = gbm_dev
}).value();
wrap_texture
Wrap an existing DMA-BUF-backed texture.
Result<texture> wrap_texture(const texture_wrap_desc &desc);
get_egl_image / get_dmabuf_fd
Extract native handles from a nozzle texture.
void *get_egl_image(const texture &tex);
int get_dmabuf_fd(const texture &tex);
OpenGL Interop
Linux GL interop uses DMA-BUF mmap for texture transfer:
#include <nozzle/backends/opengl.hpp>
nozzle::gl::gl_texture_desc gl_desc{
.name = gl_texture_name,
.target = GL_TEXTURE_2D,
.width = 1920,
.height = 1080,
.format = nozzle::texture_format::rgba8_unorm
};
// Publish GL texture → DMA-BUF mmap → shared buffer
nozzle::gl::publish_gl_texture(sender, gl_desc);
// Copy received frame → DMA-BUF → glTexSubImage2D
auto frame = receiver.acquire_frame({.timeout_ms = 1000}).value();
nozzle::gl::copy_frame_to_gl_texture(frame, gl_desc);
DRM Format Codes
| Nozzle Format | DRM Fourcc |
|---|---|
r8_unorm |
DRM_FORMAT_R8 |
rg8_unorm |
DRM_FORMAT_GR88 |
rgba8_unorm |
DRM_FORMAT_RGBA8888 |
bgra8_unorm |
DRM_FORMAT_ARGB8888 |
r16_float |
DRM_FORMAT_R16 |
rgba16_float |
DRM_FORMAT_RGBA16161616F |
r32_float |
DRM_FORMAT_R32 |
rgba32_float |
DRM_FORMAT_RGBA32323232F |
Requirements
- Linux with DRM/KMS support
- glibc 2.31+
- GBM library (
libgbm) - EGL
- Mesa or compatible GPU driver with DMA-BUF support