автор Крис Диксон

Tl; dr: Мы только что выпустили AWS AMI для потоковой передачи компьютерных игр с чрезвычайно низкой задержкой и 60 FPS от Amazon. Смотрите здесь.

Вдохновение

В июле прошлого года я прочитал высоко оцененную статью в Hacker News, в которой утверждалось, что можно играть в игры с экземпляра AWS GPU. Я немедленно выполнил шаги, описанные в статье, и вскоре стал интерактивно транслировать игры Steam через Интернет. Это было далеко не идеально, но намного лучше, чем я ожидал; Шутеры от первого лица были довольно неиграбельными, но игры консольного стиля, такие как Ведьмак 3, были более снисходительными к задержкам. Хотя есть много возможностей для улучшения, я был убежден, что некоторая итерация технологии, описанной в этой статье, коренным образом изменит нашу игру, и мне нужно было принять в ней участие.

Так началось наше путешествие к пониманию проблемы задержки в облачных играх, а затем попытка решить эту проблему наилучшим образом с помощью Parsec. В облачных играх общая задержка 20 мс по сравнению с общей задержкой 40 мс может быть разницей между отличным и неиграбельным, поэтому каждая миллисекунда на счету.

Parsec предназначен для высокой оптимизации для потоковых игр с небольшим набором других функций для обработки таких вещей, как аутентификация, переадресация портов и совместное использование. Кроме того, он призван убрать вас с пути и позволить вам наслаждаться играми. Parsec дает вам полный доступ к рабочему столу и работает с любой программой, будь то игра или нет. Вы можете думать об этом как о приложении для удаленного рабочего стола на стероидах.

В этой статье я кратко опишу, как работает наша технология (если вас интересует более подробная информация, дайте нам знать, чтобы мы могли опубликовать продолжение) и меры, которые мы приняли для устранения задержки, где бы она ни скрывалась. Parsec готов для личного использования (через LAN или WAN), и у нас также есть EC2 AMI available для быстрой настройки облака.

Все оборудование, всегда: повышение производительности H.264

По своей сути Parsec - это высокопроизводительное приложение для потоковой передачи видео. Обычно процесс выглядит так:

  1. Захват необработанных кадров рабочего стола
  2. Кодировать необработанные кадры
  3. Отправить закодированные кадры по сети
  4. Расшифруйте кадры
  5. Отрисовываем кадры на экране

Windows (начиная с 8.1) предлагает очень эффективный API для захвата кадров рабочего стола. Desktop Duplication API по существу дает вам прямой захват кадра из буфера и помещает кадр в видеопамять для обработки. К сожалению, до тех пор, пока сетевая технология не станет намного лучше, эти кадры нуждаются в некотором типе сжатия для потоковой передачи по сети с любой разумной частотой кадров. А когда дело доходит до сжатия, H.264 - действительно единственный жизнеспособный выбор. Да, есть и другие кодеки, в первую очередь H.265, но позвольте мне объяснить.

Мы в Parsec приняли решение поддерживать кодирование и декодирование видео только с аппаратным. Это означает, что мы всегда перекладываем эту обработку видео на специальные ASIC на вашем GPU, специально предназначенные для кодирования / декодирования определенных видеокодеков. H.264 отличается тем, что на сегодняшний день является наиболее широко поддерживаемым среди поставщиков оборудования и, таким образом, является выбором по умолчанию для Parsec. H.265 получает более широкую поддержку и скоро станет опцией в Parsec, но до массового распространения H.265 мы решили полагаться на более широко распространенный H.264.

А почему только аппаратная поддержка? Потому что производительность, как правило, ужасна, когда ЦП пытается обрабатывать видео, и мы не хотели бы предлагать это в качестве опции. Младшие процессоры могут изо всех сил пытаться достичь 60 кадров в секунду при более высоких разрешениях, и даже если они это сделают, обычно возникает огромная задержка. Устройства H.264 с аппаратной поддержкой начали появляться примерно в 2012 году, поэтому, если у вас есть устройство, выпущенное за последние четыре года, вы, вероятно, готовы.

Когда дело доходит до поставщиков оборудования для графических процессоров, наибольшую тройку составляют NVIDIA, AMD и Intel. У каждого поставщика есть свой API-интерфейс C для взаимодействия с оборудованием для обработки видео, а с разными API-интерфейсами связаны разные особенности и настройки производительности. Parsec напрямую реализует эти библиотеки от всех трех поставщиков, без оболочек. В зависимости от того, насколько свежи ваши графические процессоры, мы наблюдали общие задержки кодирования / декодирования менее 10 мс, намного ниже, чем мы ожидали, и намного лучше, чем задержка была в последние годы.

OnLive была основана в 2003 году, и недавнее независимое исследование показало, что их задержка составляла 150 мс, что делало большинство игр Twitch неиграбельными. Parsec значительно улучшил этот опыт, но это было бы невозможно без технологических прорывов, сделанных с момента появления OnLive в 2003 году.

Нулевое копирование, преобразование цвета и рендеринг

Работа с H.264 - это только половина дела. Как упоминалось выше, Desktop Duplication API захватывает кадры в видеопамять. С этого момента Parsec разработан таким образом, чтобы никогда не позволять необработанным кадрам касаться системной памяти, что потребовало бы от ЦП копирования необработанных данных кадра из графического процессора. Это означает, что необработанный захваченный кадр должен передаваться непосредственно в кодировщик, а затем после того, как кадр декодируется в видеопамять на клиенте, он отображается на экране напрямую без каких-либо промежуточных операций ЦП. Любое копирование в системную память будет иметь заметное влияние на задержку.

Здесь все может быть сложно; Если вы когда-либо работали с необработанным видео раньше, вы, вероятно, хорошо знаете о преобразованиях цветовых форматов, в частности, из формата стиля RGBA в формат YUV и наоборот. Для тех, кто никогда не слышал о цветовых форматах, позвольте мне рассказать вам.

RGBA легко понять. Допустим, у вас есть изображение с разрешением 1920x1080 пикселей в формате RGBA, в частности в формате 4 байта на пиксель. Примерно 2 миллиона пикселей, размером около 8 МБ. Каждый пиксель состоит из 4 байтов, из которых 1 байт выделен для каждого цветового канала R, G, B и A в указанном порядке. Эти четыре канала смешиваются вместе, чтобы создать один цвет на пиксель (также со значением непрозрачности в случае A), и это действительно все.

Цветовые форматы YUV работают иначе. Существует много различных форматов YUV, но формат NV12 является наиболее широко представленным среди библиотек обработки видео, так что именно об этом я и буду говорить в этой статье. NV12 - это планарный формат, означающий, что одна часть кадра содержит непрерывную Y-компоненту «яркости», а другая часть кадра - УФ-компонент «цветности». Для простоты вы можете думать о компоненте Y как о монохромном изображении необработанного кадра, а о компоненте UV как о цвете, который смешивается с этим монохромным изображением. Таким образом, наш тот же необработанный кадр 1920x1080 в NV12 будет начинаться с блока 1920x1080 Y размером 1 байт, по сути, монохромных пикселей. Сразу после блока Y у нас есть блок чередующихся компонентов U и V, полный блок ровно половину высоты и ширины блока Y.

Так почему это проблема? Если вы когда-либо работали с OpenGL или DirectX, вы знаете, что задний буфер (место, где происходит рендеринг) ожидает некоторого типа формата RGBA. Вывод декодера в NV12 должен быть преобразован, если мы хотим его визуализировать и отображать на экране.

Учитывая фундаментальные различия в двух цветовых форматах, преобразование из одного в другой является дорогостоящим процессом, когда выполняется на ЦП. Вот почему Parsec выполняет все преобразования цвета на графическом процессоре с помощью пиксельных шейдеров, как с OpenGL (macOS), так и с DirectX (9 и 11 в Windows). Окончательное преобразование визуализирует необработанный кадр непосредственно в задний буфер, который затем может быть эффективно отображен на экране. Необработанный кадр никогда не покидает графический процессор, улучшая задержку и экономя центральному процессору много дополнительной работы.

Если вам нужна дополнительная информация о том, как мы настраиваем эти шейдеры в OpenGL или DirectX, сообщите нам об этом в комментариях.

Возможности для улучшений: синхронизация кадров

Итак, мы наконец-то передали этот кадр в задний буфер с максимальной эффективностью. Но теперь его нужно поменять местами на передний буфер и отобразить на экране. Звучит несложно, и если вас устраивает разрыв видео, это не так. Лучший результат с точки зрения задержки - вообще не откладывать этот обмен и менять его сразу после рендеринга кадра. К сожалению, разрывы, которые могут возникнуть при использовании этой техники, недопустимы, поэтому требуется какая-то синхронизация с частотой обновления вашего монитора - также известная как V-sync.

Дополнительная проблема с облачными играми заключается в том, что кадры поступают с непредсказуемыми интервалами. Было бы неплохо, если бы мы получали кадры с точностью 60 FPS с ровно 16,66667 мс между ними. Но даже в этом случае у вас есть проблема, потому что частота обновления экрана клиента никогда не будет точно соответствовать частоте, которую вы получаете кадры. В результате V-синхронизация либо накапливает кадры, либо пропускает кадры, либо, если она отключена, вызывает разрыв. Буферизация может решить проблему, но я не должен говорить вам, что это исключено :)

Для нас это область постоянного тестирования и экспериментов. Parsec по умолчанию включает V-синхронизацию, но отбрасывает накопленные кадры, если частота кадров на сервере немного выше, чем у клиента. С OpenGL в macOS у вас нет большого контроля, но с DirectX есть множество различных эффектов подкачки на выбор, чтобы попытаться оптимизировать это. В настоящее время Parsec по умолчанию использует эффект последовательного переворота, так как он дает наилучшую производительность. Мы рассматриваем возможность сделать это расширенным вариантом в будущем, поскольку разные эффекты подкачки, похоже, работают по-разному на разных машинах. Вертикальную синхронизацию можно отключить на панели управления для тестирования.

Звучит круто, но…

Вы можете подумать: «Да, все это круто, но как насчет задержки в сети. Вы ничего не можете с этим поделать ».

Ты прав. Мы ничего не можем с этим поделать. Но Parsec задумывался как перспективный продукт, который сможет превратиться в усовершенствования инфраструктуры сети, и, судя по всему, дела быстро улучшаются, поскольку правительство продвигает дальнейшие инвестиции в широкополосную связь до такой степени, что больше более 90% США имеют интернет со скоростью 25 Мбит / с.

Сейчас облачные игры могут работать не для всех, но, вероятно, довольно скоро они будут работать для большинства. Благодаря задержкам сети ниже 20 мс и пропускной способности выше 10 Мбит / с Parsec предлагает почти нативную работу.

Вы можете рассматривать Parsec как исследовательский проект, целью которого является устранение задержки в облачных играх. Первая итерация может быть не на 100%, но вы можете быть уверены, что мы работаем каждый день, чтобы найти способ избавиться от этой следующей миллисекунды.

И как однажды сказал Аль Пачино:

«Облачные игры - это игра на миллисекунды. В Parsec мы боремся за эту миллисекунду. Мы царапаем ногтями эту миллисекунду. Потому что мы знаем, что когда мы складываем все эти миллисекунды, то разница между победой и проигрышем будет чертовой.