Как герои игры OverWatch однажды облысели, а мы вернули им шевелюры
Почему сложно поддержать DirectX в полном объеме
На самом деле, виртуальная машина РС, позволяющая запускать Windows на Mac, сама по себе не гарантирует, что в ней будут работать PC-игры. Дело в том, что большинству игр требуется поддержка DirectX определенной версии со стороны видеоадаптера, и обеспечение этой поддержки полностью ложится на плечи разработчиков видеодрайверов. Естественно, что видеодрайвера, разработанные для «настоящих» видеокарт Nvidia, AMD и Intel, в виртуальной машине работать не будут.
На данный момент последней версией DirectX является DirectX 12, но она еще не получила широкого распространения. Другое дело — версия DirectX 11, уже достаточно популярная среди разработчиков игр. Правда, начиная с DirectX 10 существует — и активно применяется на практике — возможность работать с версией DirectX 11 и выше на видеокарте, поддерживающей, например, только DirectX 10, с ограничением функциональности, поэтому большинство новых игр, написанных для DirectX 11, могут работать на DirectX 10 без заметной визуальной разницы.
Мы обеспечиваем поддержку DirectX, начиная с самых первых версий Parallels Desktop для Mac. По мере эволюции Windows и DirectX, Parallels Desktop также развивался. Мы поддерживали DirectX 7, DirectX 8, DirectX 9, и уже несколько лет — и DirectX 10, что в свете вышеописанного особенно важно. Но та часть функциональности DirectX 10, которая касается работы видеодрайвера — правила, по которым надо трактовать его команды и создавать изображение — описана в документации довольно сжато. Количество разных комбинаций, состояний, вызовов — очень большое, и просто прочитать спецификацию, чтобы создать по ней однозначный программный код, которой позволит запускаться и работать любой PC-игре, к сожалению, нереально.
Кроме того, следует знать, что мы обеспечиваем поддержку DirectX 10 через OpenGL, т.е. преобразуем команды для DirectX в команды для OpenGL. Но одна и та же конструкция в OpenGL и в DirectX может работать несколько по-разному, и в разных условиях могут отрисовываться разные картинки. Что же остается? Остается работать методом проб и ошибок, т.е. запускать современные игры, которые пользуются функциональностью DirectX 10, и работать над ошибками.
Наша борьба с Overwatch
Проверить нашу поддержку DirectX 10 мы решили на примере игры Overwatch — многопользовательской «стрелялки», выпущенной компанией Blizzard Entertainment для всех основных игровых платформ, т.е. для PC, PS4 и Xbox One —, но не для Mac. Игра Overwatch пользуется возможностями DirectX 10 очень интенсивно, поэтому она оказалась хорошим тестом на прочность для нашего DX10-драйвера. И игра заработала —, но с множеством проблем. Многие вещи отрисовывались неправильно, медленно. Вот как выглядела игра поначалу.
Ниже мы опишем лишь три проблемы из тех, с которыми нам пришлось столкнуться.
Элементы управления и пункты меню
Первое, что бросилось нам в глаза — на видеокартах NVidia и Intel игра Overwatch не отрисовывала часть пунктов меню, индикаторов и значков. Проблему мы нашли довольно быстро — она оказалась связана с расхождением в трактовке значений встроенной переменной VertexID в вершинных шейдерах. В случае индексной отрисовки в DirectX эта переменная равна значению «индекса вершины», а в случае работы через OpenGL к нему еще прибавляется значение BaseVertex. Шейдеры, генерирующие текстуру, которая затем используется для отображения меню и других «плоских» элементов игры, используют в своем коде сравнение VertexID с предопределенными значениями. Поскольку драйверы для NVidia и Intel работают согласно спецификации OpenGL, они выдают неправильную картинку. Драйверы для AMD, напротив, не прибавляют BaseVertex к VertexID, в результате ошибка накладывается на ошибку и получается правильный результат.
Можно было бы легко исправить ситуацию с помощью расширения GL_ARB_shader_draw_parameters (http://www.opengl.org/registry/specs/ARB/shader_draw_parameters.txt), но, к сожалению, Mac его не поддерживает — во всяком случае, пока. Мы нашли другое решение — когда используются видеокарты NVidia и Intel, мы передаем значение BaseVertex внутрь шейдера, и затем вычитаем его из gl_VertexId. В итоге получается значение переменной, корректное с точки зрения DirectX 10 числа. На видеокартах от AMD этого, естественно, не происходит.
Проблема с тенями
На самом деле тени объектов рисовались в Overwatch правильно. Зато на всех освещенных участках были заметны полоски.
После того, как мы детально разобрались с шейдерами, причина обнаружилась в настройке состояния OpenGL. Функция RasterizerState компонента Direct3D 10 Runtime имеет три значения, задающие корректировку глубины полигонов: DepthBias, DepthBiasClamp и SlopeScaledDepthBias. Их аналог в OpenGL сводится к вызову glPolygonOffset с правильными параметрами, и наша ошибка заключалась в том, что при нулевом значении DepthBias мы не предполагали, что SlopeScaledDepthBias может быть не равен нулю, поскольку считали, что корректировка глубины полигонов в этом случае выключена.
Отчего выпадают волосы
Тот факт, что все персонажи игры Overwatch под Parallels Desktop либо полностью потеряли свои шевелюры, либо постриглись «под ежик», вызвал бурную реакцию в социальных сетях и породил много шуток.
Однако стоит заметить, что «оттягиваясь» на полысевших героях, добродушно настроенные пользователи не заметили, что в игре отсутствуют не только волосы персонажей, но и некоторые другие объекты. Тестирование показало, что причина этой экзотической ошибки — в нехватке свободных текстурных каналов. В OpenGL их может быть не более 16 на каждый тип шейдера. Это ограничение было связано с тем, что использование текстурных каналов с номерами 16 и выше на видеокартах AMD приводит к порче состояния OpenGL в драйвере и проблемам в последующих отрисовках. В результате вместо всех остальных текстур, участвующих в отрисовке, шейдер получал черный цвет, что в ряде случаев приводило к полному пропаданию рисуемого объекта со сцены. Надо сказать, что от самой проблемы мы, конечно, не избавились, но поскольку в Overwatch негативный эффект от снятия данного ограничения оказался минимальным, мы решили для данного случая от него избавиться. Стоит отметить, что в общем случае проблема дефицита текстурных каналов в OpenGL по сравнению с DirectX 10 стоит остро, т.к. последний теоретически позволяет использовать до 128 ресурсов в одной отрисовке, и спасает только то, что приложений, пользующихся такой возможностью, довольно мало.
Результат
Вся работа заняла у нас меньше месяца, и исправив ошибки — как описанные, так и ряд других — мы добились того, что теперь наши пользователи действительно могут играть в Overwatch под Parallels Desktop для Mac, и эта игра работает в условиях виртуализации довольно быстро. Эта скорость, конечно, не сравнима со скоростью работы Overwatch на РС, и в случае серьезных нагрузок игра тормозит. Но цель «догнать и перегнать PC» нами и не ставилась. На примере Overwatch мы нашли проблемы в работе нашего виртуального драйвера и смогли их исправить. Полученные результаты помогут в поддержке работе других 3D-приложений. И, конечно, ничто не сравнится с положительной обратной связью от пользователей Mac — ведь теперь благодаря нам они могут играть на этой платформе в свои старые любимые игры, переносом которых на Mac уже никто и никогда бы не озадачился.
Когда же появится поддержка DirectX 11
Дело в том, что OpenGL на Mac’ах развивается медленно и всегда заметно отстает от последних актуальных версий. Даже для поддержки DirectX 10 нам зачастую не хватало имеющейся функциональности OpenGL на Mac, приходилось прибегать к различного рода ухищрениям и эмулировать недостающие возможности самостоятельно. Сейчас Mac поддерживает OpenGL 4.1 и этого кое-как хватает для DirectX 10, но для 11-ой версии недостает ряда ключевых возможностей, например, compute-шейдеров. Так что, многое зависит от того, будет ли Apple дальше развивать OpenGL на своих машинах.
Комментарии (3)
20 сентября 2016 в 10:33
0↑
↓
Спасибо за статью! Мне всегда интересно читать про то, какие «костыли» приходятся пилить людям в рамках ограниченной функциональности платформы,20 сентября 2016 в 10:35 (комментарий был изменён)
+2↑
↓
У меня просто в голове не укладывается, как можно на техническом ресурсе, каковым является Хабр, брать картинку 1920×1080 в PNG весом в добрые 3,5 МБ, ужимать её средствами HTML до маленького прямоугольничка, при этом ещё и искажая пропорции, и помещать её до ката.20 сентября 2016 в 10:36 (комментарий был изменён)
0↑
↓
valve под windows-то — периодически всех бреетps — не могу картинку вставить почему-то