Взаимодействует ли libdrm с ядром DRM / видеокартой через ioctl()?

#c #graphics #linux-kernel #ioctl #drm

#c #графика #linux-ядро #ioctl #drm

Вопрос:

Это может быть глупый вопрос, поскольку я вообще мало что знаю об этой теме… Похоже, что пользовательские приложения могут напрямую взаимодействовать с GPU для рендеринга изображения, например, с использованием OpenGL, через mesa и libdrm, где libdrm является оболочкой для различных вызовов ioctl(), как показано на этом графике. Означает ли это, что для каждого нового кадра 3D-игры игровое приложение должно вызывать ioctl() один раз (или, может быть, даже дважды, если необходимо достичь KMS)? Это звучит как преодоление большого барьера пространства между пользователем и ядром (думая об игре со скоростью 120 кадров в секунду).

Ответ №1:

libdrm — это оболочка пользовательского пространства для выполнения детального доступа к базовым функциям драйвера KMS, таким как настройка режимов, проверка того, является ли используемая плоскость плоскостью наложения или основной плоскостью и т.д. реализации libdrm, как правило, отличаются для различных комбинаций CPU / GPU / OS, поскольку драйвер h / w, работающий в ядре, как правило, поддерживает другой набор функций, отличный от стандартных. Стандартный способ работы с libdrm — открыть устройство drm, доступное в /dev/ узле, и выполнить вызовы функций libdrm, используя fd, возвращаемый из open() .

Чаще всего программное обеспечение display compositor для конкретной ОС, такой как X11, wayland, hardware-composer, должно контролировать устройство drm, что означает, что непривилегированные приложения не могут быть хозяином DRM. Большинство функций настройки режима libdrm не работают, если приложение, пытающееся их использовать, не является хозяином DRM. Рекомендуемая практика вместо прямого использования libdrm — использовать стандартную графическую библиотеку, такую как OpenGL или VULKAN, для подготовки и рендеринга фреймов в вашем приложении.

Количество ioctl, требуемое для взаимодействия с модулем ядра DRM, скорее всего, не является самым большим узким местом, с которым вы столкнетесь при попытке рендеринга приложений с высокой частотой кадров в секунду. Предпочтительный способ запуска приложений с высокой частотой кадров при взаимодействии с дисплейным редактором целевой системы — это иметь

  • настройка с двойной или тройной буферизацией для рендеринга, при которой следующий буфер, подлежащий рендерингу, готов к рендерингу до завершения рендеринга текущего кадра.
  • Используйте ускорение h / w везде, где это возможно, например, для выполнения масштабирования / изменения размера / преобразования формата изображения / преобразования цветового пространства.
  • Предварительное вычисление и повторное использование элементов шейдера
  • Старайтесь как можно чаще использовать элементы текстуры вместо того, чтобы вычислять много текстур для каждого отображаемого кадра.
  • Используйте векторные / SIMD / SSEv2, 3, 4 / AVX / neon инструкции везде, где это возможно, чтобы воспользоваться преимуществами современных конвейеров процессора

Комментарии:

1. Спасибо за ответ. Итак, в конце концов, реализованы ли вызовы функций libdrm с использованием ioctl()? Что мне интересно, так это то, что пользователю в конечном итоге необходимо получить доступ к функциям внутри ядра DRM или к любым функциям модуля ядра, статически / динамически загружаемым, и ioctl (), похоже, является единственным способом в этом случае, это правильно? Еще вопросы, касающиеся ваших комментариев, когда у пользователя есть двойной буферный буфер и он выполняет рендеринг в эти буферы либо с ускорением h / w, либо без него, эти вызовы рендеринга в конечном итоге также должны выполняться с помощью вызова ioctl (), это правильно?

2. Я предполагаю, что мой вопрос заключается в следующем — чтобы вызвать функции ядра / модуля из пользовательского пространства или отобразить что-либо в RAM / VRAM, пользователь должен преодолеть барьер user / kernel, и он может сделать это только через стандартные системные вызовы или вызовы ioctl (что является своего рода универсальным интерфейсом), и других способов нет. Это верно?

3. @QnA Это верно, взаимодействие с ядром для рендеринга, а также использование графического процессора для подготовки сцены перед рендерингом кадра происходит через ioctls на устройстве DRM. Подсистема DRM обеспечивает как взаимодействие графического процессора с ОС, так и взаимодействие с дисплеем. Приложения, использующие подсистемы графического процессора / дисплея, используют ioctls прямо или косвенно для взаимодействия с ядром

4. Это очень помогает, еще раз спасибо. Я понимаю, что ваш ответ шире / глубже, чем мой первоначальный вопрос, но потерпите меня еще секунду… Таким образом, вызов ioctl должен выполняться (прямо или косвенно) по крайней мере один раз (а может быть, и больше) за кадр, например, некоторые подготовительные работы, за которыми следует рендеринг, а затем «Я закончил, иди отобрази это»? И вы сказали, что 120 вызовов ioctl в секунду для игры со скоростью 120 кадров в секунду не так уж дорого по сравнению с другими затратами, это верно?

5. @QnA Да, должен быть по крайней мере 1 вызов ioctl, который выполняется за кадр, особенно для «Я закончил, иди отобрази это». более 120 ioctls в секунду не должны быть дорогостоящей командой или не должны быть узким местом для приложения по сравнению с другими областями, которые я упомянул в ответе