Russian Fedora

cообщество русскоязычных участников
международного проекта Fedora

Virgil 3D

Это архивная статья

Инженер Red Hat и участник Fedora и Debian David Airlie рассказал о текущем состоянии Virgil 3D (статья за paywall) на прошедшем LinuxCon North America. Мы уже вкратце упоминали про Virgil 3D, и возможно пришла пора рассказать о нем, и проблеме, которую он решает, поподробнее.
Очень хочется предоставлять виртуальным машинам возможности 3D-ускорения, имеющиеся на хостовой системе. Сейчас есть лишь проприетарные решения. Virgil 3D, это как раз открытый вариант. Сейчас он использует Mesa, но в будущем планируется добавить и DirectX и Direct3D драйверы.

Исходная задача Airlie сказал, что решение VMware "лучший вариант из существующих" для виртуального GPU. Однако, он основан на DirectX 9, так что у него ограниченные возможности, и он проприетарный, кроме куска, который работает в гостевой системе Linux. У VirtualBox тоже есть решение, но оно основано на OpenGL, который является "худшим вариантом", т.к. его сложно сделать безопасным. У OpenGL есть слишком много точек входа, и для приложения в userspace очень легко добиться переполнения буфера или создать иные проблемы. Также есть драйвер vGallium, но это лишь исследовательский проект, до сих пор не достигший уровня пригодности для широкого использования.

Virgil 3D основан на virtio, на стандарте для виртуализированного ввода/вывода (I/O), созданном Rusty Russell. Основная идея virtio, это набор очередей для взаимодействия с драйвером, наряду с конфигурационным пространством, которое может выглядеть как PCI.

С графической части Mesa реализует OpenGL, а ее часть Gallium3D упрощает разработку 3D-драйверов. Под Mesa есть еще EGL API, который сидит между OpenGL и оборудованием. EGL был изначально спроектирован для встраиваемых устройств, но он теперь "все чаще и чаще используетсядля всего подряд", сказал David, и однажды "захватит всё". Еще одна часть мозаики, это SPICE, протокол для "удаленного десктопа" — он предоставляет удаленный доступ к аудио, видео, устройствам ввода-вывода и т.п. На реальном графическом оборудовании обязательно есть что-то типа ring buffer, куда ядро отправляет команды. Графические драйверы из userspace создают потоки таких команд (которые манипулируют текстурами, surface, шейдерами и т.п.), чтобы передать их в ядро.

Эти userspace-команды должны рассматриваться, как небезопасные. Они копируются в ядро, затем проверяются, чтобы превратить их в "безопасные" команды. А уже эти команды затем помещаются в ring buffer, за которыми располагается защитная операция (fence). Т.к. GPU асинхронное, то ядро может узнать, что набор команд был выполнен, лишь по порядковому номеру, присвоенному уже выполненной защитной операции (fence).

Поддержка 2D Первая задача для Virgil 3D, задолго до перехода к "3D части, в которой я был заинтересован", была, это запустить базовый virtio GPU драйвер, сказал Airlie. Он поддерживал несколько мониторов, хардверные курсоры, и базовый набор 2D команд. Драйвер предоставлял memory-mapped I/O, PCI, или VGA устройства, и должен был работать на любой архитектуре, что поддерживала virtio. "Базовым компонентом был командный ring buffer", хотя оригинально было задумано два кольцевых буфера, и один для защитных операций (fence). Разработчик QEMU переписал его для использования лишь одного командного ring buffer — кольцевой буфер для защитных операций (fence) может быть добавлен попозже, если его отсутствия станет проблемой.

Базовый объект в драйвере, это ресурс, сказал Airlie, и каждый ресурс обладает уникальным идентификатором. Для 2D, каждый ресурс обладает шириной, высотой, битовой глубиной, привязанных к нему. Для 3D, есть еще "целый букет" атрибутов, и это "гораздо сложнее". Гость просто ссылается на ресурс по его идентификатору, а хост выделяет память и создает собственно ресурс. Драйвер получает страницы памяти гостевой системы, чтобы присоединить их к ресурсу.

Ресурсы отображаются в объекты OpenGL. Для 2D, драйвер просто копирует данные из гостевых страниц памяти, присоединенных к ресурсу, в объект OpenGL. Передавать данные 3D в хостовую систему гораздо сложнее, сказал Airlie. Для 2D хост просто передает данные, а для 3D можеть быть необходимость в вычитывании данных из оборудования назад, в гостевую систему.

Этот простейший драйвер предоставляет "ресурсы и способ наполнить их данными", сказал David; следующий шаг, это превратить ресурс в "передний объект", чтобы "люди могли его увидеть". Это сделано с помощью set_scanout(), что примерно тоже самое, что и выбор режима работы на обычном графическом устройстве. Также нужно вызвать flush_resource(), чтобы вызвать перерисовку OpenGL. Все это "основа простейшего GPU", большая часть которого уже включается в QEMU.

3D Для 3D, поток небезопасных команд создается из Mesa в гостевой машине, и отправляется в драйвер с помощью команды SUBMIT_3D. Создаются 3D-контексты для каждой user-space программы из гостевой системы, и к ним присоединяются ресурсы. Это означает, что гостевая программа не обладает доступом к ресурсу, который она не создала, т.к. он просто не будет присоединен к 3D-контексту.

У потока 3D-команд есть несколько типов действий. Есть действия над состоянием объекта (создать, привязать, уничтожить), над различными типами шейдеров (включая вертексы, фрагменты и геометрию), по управлению поверхностями (surface) и текстурными объектами и т.п. Кроме того, есть также операции рендеринга, например draw, clear, и blit. Также есть набор команд, которые завершают набор 3D-команд. Всем этим нужно управлять в Virgil 3D.

Необходимо пять несвязанных компонентов, чтобы это все заработало в Linux, сказал Airlie. Два куска работают на хостовой машине: virtio GPU драйвер в QEMU и в библиотеке рендеринга. Причем, последний, это довольно большая работа. Гостевое ядро должно обладать DRM/KMS (direct rendering manager/kernel mode setting) драйвером, который поддерживает virtio GPU. В user-space ему нужен Gallium3D-драйвер для Mesa, чтобы общаться с ядром, и может понадобиться device-dependent X (DDX) драйвер для X-сервера.

Когда Airlie начал работу над проектом Virgil 3D, QEMU поддерживал лишь Simple DirectMedia Layer (SDL) 1.2 для графики, и там не было поддержки нескольких мониторов. Это значило, что QEMU нужно было портировать на SDL 2.0. Эта работа уже включена в апстрим QEMU. А код virtio GPU находится "в чьем-то дереве исходников", и пока направляется на включение в QEMU.

Библиотека для рендеринга, это то, "где вся веселуха", сказал он.

Она получает поток команд, и превращает их в вызовы OpenGL API. Она также преобразовывает шейдеры в GLSL (язык для шейдеров, использующийся в OpenGL).

В рабочей конфигурации используется SPICE, чтобы общаться с виртуальной машиной QEMU, запущенной в libvirt. Это значит, что только клиент удаленного десктопа напрямую общается с графическим железом, что не то, что планировалось. Хотелось бы, чтобы QEMU тоже общался с железом.

Чтобы этого добиться, код использует dma_buf фичу ядра и передает файловые дескрипторы из QEMU в клиент удаленного десктопа и обратно. Однако SPICE использует TCP, а дескрипторы могут передаваться лишь по Unix-сокетам. Так что пока David подкрутил кое-какие права доступа у Unix-сокетов, временно назначив им права 777, чтобы хоть как то все это запустить.

Есть некоторые проблемы с OpenGL, которые надо поправить, включая то, как работать с фичами GL 3.1, которые используются редко, и которые непросто реализовать. Если на хостовой машине что-то использует GL 3.1, то Virgil 3D будет нужно как-то это обрабатывать, но GL 3.1 сейчас не реализован для Linux (и для Apple, кому интересно). Много функциональности из 3.1 может быть реализовано с помощью других фич и команд OpenGL, так что их теоретически возможно эмулировать.

TODO-лист для Virgil 3D довольно короткий, сказал Airlie, но все пункты в нем "огромны". В список входят корректная обработка возможностей OpenGL, использование текстового представления шейдеров в формате TGSI (Tungsten Graphics Shader Infrastructure) вместо бинарного, используемого сейчас (что будет "проблематично"), уже упомянутая проблема с GL 3.1, многопоточность в GL-части QEMU, и, наконец, включение всего в апстрим.

Airlie завершил свое выступление демонстрашкой 3D-игры Xonotic, запущенной в виртуалке на его ноутбуке. Получилось, как он сказал, 60 fps, "по крайней мере". Он ответил на вопросы из зада, отметив, что использование протокола удаленного доступа по сети приведет к использованию видеосжатия на хостовой машине, и передаче результатов в программу-просмотрщик, а не прямую передачу 3D-объектов и команд.

Он был бы рад ошибаться в этом, но в любом случае он попробует сделать передачу 3D-объектов по сети своим следующим проектом.

[`Jake Edge <https://plus.google.com/114539980002847471046/about>`__, автор оригинальной статьи, хотел бы поблагодарить Linux Foundation за помощь в поездке в Chicago на LinuxCon North America.]

Комментарии