На конференции разработчиков игр (Game Developers Conference — GDC), компании Valve и Nvidia выступили с докладом, посвященным портированию игр под Linux. Презентация с данного мероприятия доступна на сайте Nvidia.
Наиболее интересные моменты:
- В качестве мотивов почему следует портировать игры на Linux, упоминаются:
- Открытость операционной системы Linux и экосистемы.
- Довольно быстрый рост популярности Linux в качестве игровой платформы.
- Логичный промежуточный шаг при портировании игр на мобильные платформы, где также доминируют стандарты семейства OpenGL
- Производительность.
- Под Linux официально доступен Steam.
- GL предоставляет доступ к возможностям оборудования, оперируя при этом сугубо возможностями оборудования, а не версиями ОС или чем-либо еще. В частности, в Китае в данный момент все еще очень много пользователей с ОС семейства Windows XP, которые не могут пользоваться DX10/11. Тем не менее, при использовании OpenGL будут доступны полные возможности оборудования, в том числе и в данной версии ОС. Это позволит использовать возможности современного оборудования даже указанным пользователям.
- Публично доступные спецификации стандарта.
- Спецификации развиваются комитетом, в котором может принять участие любая заинтересованная сторона, для этого не требуется огромные суммы денег.
- GL проще расширять, любой вендор может предложить свои расширения.
- GL очень богат по своим возможностям.
- Для управления окнами настоятельно рекомендуют использовать SDL, относительно небольшую и кроссплатформенную библиотеку на Си. SDL берет на себя все что касается работы с окнами, независимо от ОС, в том числе и на мобильных платформах. Valve пользуется данной библиотекой при портировании своих проектов, что доказывает пригодность библиотеки для достаточно требовательных применений. Кроме того, основной разработчик libsdl в настоящее время работает в Valve.
- Проблемы с которыми столкнулись в Valve:
- Файловые системы в unix-подобных ОС по умолчанию чувствительны к регистру имён файлов, тогда как в Windows файловые системы по умолчанию игнорируют регистр. Для игр это, как правило, не является проблемой так как игровые ресурсы обычно поставляются в платформо-нейтральных контейнерах. Тем не менее, в процессе разработки это может быть проблемой. Наиболее простым решением является перевести имена всех ресурсов в нижний регистр.
- Ошибочные define’ы, например предполагающие, что на Linux может быть только выделенный игровой сервер и более ничего.
- Проблемы с локалью могут вызывать проблемы в функциях printf/scanf. Решение: установить локалью en_US.utf8, а локализацию предоставить самому приложению. Так как в некоторых случаях локаль en_US.utf8 в системе может отсутствовать, следует предусмотреть вывод предупреждения в данном случае.
- Шрифты: рекомендуется использовать библиотеки freetype и fontconfig. Тем не менее, может потребоваться пересчет размера шрифтов.
- Использование RDTSC (прецизионный таймер, основанный на счетчике тактов современных CPU х86). Вместо него рекомендуется использовать вызов clock_gettime(CLOCK_MONOTONIC), не зависящий от архитектуры процессора.
- Использование raw mouse input, когда весь ввод мыши монопольно отправляется одной программе. Это очень хорошо работает для игр, однако некоторые оконные менеджеры при этом также перенаправляют и весь клавиатурный ввод. Это, в частности, может отключить работу alt-tab или аналогичных по смыслу горячих клавиш для переключения задач, что способно вызвать неудовольствие пользователей в некоторых ситуациях.
- Более шероховатая поддержка многомониторных конфигураций. Тем не менее, libsdl способна взять бОльшую часть проблем на себя.
- Инструментарий:
- Steam Linux Runtime и SDK предоставляют разработчикам игр бинарно-совместимый ABI, не зависящий от дистрибутива.
- Компилирование и отладка:
- gcc — для компилирования.
- gdb — для отладки.
- cgdb — интерфейс на основе curses
- ldd — отслеживание зависимостей бинарного файла от библиотек (эквивалент dumpbin).
- nm — предоставляет информацию о символах, используемых программой.
- objdump — дизассемблер и инструмент для просмотра подробных деталей о бинарных файлах.
- readelf — инструмент для получения подробной информации об ELF файлах (основной формат исполняемых файлов в Linux).
- make — средство сборки проекта.
- Анализ производительности — CPU:
- perf — свободный профайлер под Linux, использующий performance counters современных процессоров
- vtune — инструмент от компании Intel, также существующий и в версии под Linux.
- Telemetry — многие коммерческие разработчики игр уже и так используют данный инструментарий.
- Примерное соответствие OpenGL и DX:
- DX9 примерно соответствует возможностям GL2. Начиная с этой версии доступны шейдеры.
- SX10 примерно соответствует семейству GL3, появилось более актуальное API. Реализованы геометрические шейдеры.
- DX11 примерно соответствует GL4. Поддержка тесселяции и произвольных вычислений на шейдерах.
- Ключевые отличия DX от GL с точки зрения разработчика:
- В GL у потоков есть локальные данные, поэтому:
- У потока может быть только один текущий контекст.
- Контекст может являться текущим только для одного потока.
- Вызовы в GL из потока без текущего контекста согласно спецификации не должны иметь никакого эффекта.
- GL основан на си. Объекты передаются хэндлами.
- Многие функции вообще не требуют указания хэндла и оперируют на выбранном в данный момент объекте.
- Как правило хэндл имеет тип GLuint.
- GL поддерживает расширения.
- Несмотря на то что GL довольно многословен и на первый взгляд требует больше вызовов, он показывает впечатляющую эффективность и производительность.
- В OpenGL отсуствуют проблемы с потерей устройств.
- В GL у потоков есть локальные данные, поэтому:
- Расширения OpenGL:
- Есть специфичные для поставщиков расширения с префиксами NV|AMD|APPLE. Тем не менее, ряд из них был реализован сразу несколькими поставщиками. Например, NV_bindless_texture.
- Расширения с префиксом EXT реализуются сразу многими поставщиками. Например, EXT_separate_shader_objects
- Расширения с префиксом ARB были рассмотрены и приняты комитетом развивающим стандарт. Например, ARB_multitexture.
- Базовые расширения (Core extensions): базовые возможности из более поздних версий стандартов GL представляются как расширения относительно прошлой версии стандарта.
- Есть зависящие от специфики платформы расширения: WGL, GLX, AGL и EGL.
- Советы разработчикам:
- Поиск в интернете имеет смысл делать как с префиксом GL_ или gl у соответствующего вызова так и без него.
- Чтение спецификаций стандарта себя оправдывает многократно.
- Если вам не нравится текущее направление развития GL, присоединитесь к Khronos Group и постарайтесь оказать влияние на развитие стандарта. Лучше всего определять свое будущее самому.
- Core vs Compatibility: Некоторые производители утверждают что использование core-профайлов будет быстрее чем compat-, однако по факту подтверждение данного тезиса обнаружить не удалось. Поэтому можно пользоваться тем, что проще и удобнее конкретному разработчику.
* Наиболее полезные расширения GL по мнению разработчиков:
EXT_direct_state_access, EXT_swap_interval (и EXT_swap_control_tear), ARB_debug_output, ARB_texture_storage и ARB_sampler_objects. Кроме того отмечаются NVX_gpu_memory_info и GL_ATI_meminfo позволяющие получить информацию о использовании памяти GPU.
- Самые проблематичные места в плане производительности:
- Вызов MakeCurrent очень дорогой. Следует избегать его вызова даже 1 раз на кадр.
- Современные драйвера как правило используют более 1 потока. Программа по факту взаимодействует с относительно тонкой прослойкой которая может распределять работу на несколько потоков. Некоторые вызовы заставляют производить полный сброс буферов и ресинхронизацию между потоками что сильно просаживает скорость операций.
- Наиболее проблемными зарекомендовали себя следующие функции glGet() и glGetError() (вместо этой функции рекомендуется использовать ARB_debug_output)