Неуловимая проблема тайминга кадров

https://medium.com/@alen.ladavac/the-elusive-frame-timing-168f899aec92
  • Перевод

Технический директор Croteam Ален Ладавач, участвовавший в разработке Serious Sam и Talos Principle, рассказывает, как ему удалось найти причину торможения графики даже на самых мощных машинах.

Наконец-то появилось объяснение того, почему некоторые игры тормозят на вашем PC (и луч надежды на то, что в ближайшем будущем они тормозить перестанут).

Т-т-тормоза


Вы с нетерпением ждали следующей части вашей любимой серии видеоигр для PC и она наконец вышла. На этот раз вы хотите насладиться ею во всей полноте, поэтому потратили деньги и время на тщательную подготовку. Вы заменили процессор, поставили сверхсовременную видеокарту, добавили ещё ОЗУ — чёрт возьми, даже купили RAID на SSD. Игра должна быть плавной с самой заставки.

Предзаказ наконец разблокирован и вы только что завершили установку. В нервном предвкушении вы впервые запускаете игру. Пока всё хорошо — она работает с частотой 60 кадров в секунду. Или, по крайней мере, так сообщает счётчик кадров тюнера GPU. Но что-то не так. Вы делаете мышью резкие, хаотичные движения. Стрейфитесь влево-вправо, и тут игра… начинает тормозить! Блин, да как такое возможно? Как она может тормозить при 60 кадрах в секунду?

Если такое с вами никогда не случалось, то это может показаться смешным. Но если вы их испытали, то, скорее всего, ненавидите тормоза всей душой. Тормоза в играх. Это не старый добрый «лаг». Не низкая частота кадров. Это просто «тормоза», происходящие при высоких частотах кадров на идеальных, супербыстрых машинах. Что это, откуда они взялись и как от них избавиться? Позвольте мне рассказать вам историю…

Тормоза, плавность, скорость… это ведь одно и то же?


Видеоигры работали с частотой 60 fps ещё со времён первых аркадных автоматов в 70-х годах. Обычно ожидается, что игра работает с той же частотой, которая используется дисплеем. Так было до популяризации 3D-игр, в которых впервые стала допустимой пониженная частота кадров. В 90-х, когда "3D-карты" (так мы называли их до того, как они стали "GPU") начали заменять программный рендеринг, люди играли в игры при 20 fps, а 35 fps считались приличным значением для серьёзных сетевых боёв. Я не шучу.

Сегодня у нас есть супербыстрые машины и "разумеется, они могут работать при 60 fps". Однако количество разочарованных скоростью игр пользователей как никогда велико. Как такое возможно? Проблема оказывается не в том, что игры не могут работать достаточно быстро, а в том, что они тормозят, даже когда могут работать быстро!

Если почитаете разные игровые форумы, то наверняка найдёте подобные сообщения:

image

Можно подумать, что это единичные проблемы, но посмотрите на статистику поисковых запросов Google:

image

За последние пять лет тормоза (stutter) стали (относительно) более серьёзной проблемой, чем скорость!

(Учтите, что это относительные значения. Они не значат, что в целом люди спрашивают о торможениях больше, чем о частоте кадров. Они значат, что запросы о частоте кадров (frame rate) остаются на том же уровне, а количество запросов о тормозах растёт, особенно в последнее время.)

Десяток лет в поисках причины необъяснимых тормозов


image

Пациент скорее жив, чем мёртв, просто тормозит чуть больше, чем нужно.

Впервые я столкнулся с этой проблемой ещё примерно в 2003 году. Мы работали над Serious Sam 2, и пользователи начали отправлять нам отчёты о том, что они тестировали что-то на пустом уровне, и при перемещениях мыши движения не были плавными. Это сопровождалось очень характерным паттерном на графике частоты кадров, который мы прозвали «кардиограммой».

Мы думали, что где-то в коде есть баг, но не могли его найти. Казалось, что проблема появляется и исчезает случайным образом — после перезапуска приложения, перезагрузки машины… а потом игрок менял какую-нибудь опцию скорости и она исчезала. Потом игрок снова включал эту опцию, но проблема не возвращалась. Она была похожа на призрака.

Очевидно, что эта проблема возникала не только у нас. Наблюдая за теми же проблемами в других играх, мы начали думать, что виноваты драйверы. Но это происходило на видеокартах разных производителей. Даже на разных API (OpenGL, DirectX 9, DirectX 11…)  — единственным общим у них было то, что они появлялись на разных машинах, в некоторых сценах… иногда.

image

Несси, бигфут… почти столь же неуловимые, как и проблема с «кардиограммой».

Мы выпустили ещё несколько игр, но это странное поведение по-прежнему появлялось и исчезало. Некоторых пользователей оно раздражало, и мы рекомендовали им изменить опции скорости — иногда это помогало, иногда нет. Такова жизнь, не правда ли?

Но однажды, в отличный зимний день в начале 2013 года мой коллега Дин позвал меня, чтобы я увидел ещё один пример этой проблемы, который он на тот момент мог относительно стабильно воспроизводить. На этот раз проблема возникала на уровне из Serious Sam 3. Мы экспериментировали с опциями в этой сцене, пока до меня внезапно не дошло. Я понял, в чём была причина! И она была очень проста — неудивительно, что она ускользала от всех в течение десятка лет.

Изменив всего одну очень простую опцию игрового движка, мы смогли заставить эту проблему появляться и исчезать в этой конкретной сцене. Но нам стало сразу же очевидно, что на её качественное решение потребуется гораздо больше усилий. Усилий не только с нашей стороны, но и всей игровой экосистемы PC — программистов драйверов GPU, разработчиков API, поставщиков ОС — каждого.

Позвольте объяснить.

В чём же была причина всё это время


Хотел бы я показать вам её на примере сцены из Serious Sam 3, которую мы с Дином исследовали пять лет назад. Или даже ещё лучше — на примере тестовой сцены из Serious Sam 2, в которой мы впервые её увидели. Но, к сожалению, после замены «железа» этот ускользающий зверь может переместиться в другую сцену. У меня есть сцена из The Talos Principle, в которой мне недавно удалось воспроизвести эту проблему, и я заснял несколько видео, позволившие проанализировать её более подробно.

Но прежде чем мы начнём, убедитесь, что вы на самом деле смотрите видео в 60 fps. Для просмотра представленных ниже примеров переключитесь в 1080p60, как показано на картинке:

image

Чтобы смотреть видео в 60 fps, переключитесь в YouTube на 1080p60.

Если вы всё сделаете правильно, а ваш компьютер и веб-браузер способны показывать видео с частотой 60 fps, то представленное ниже видео должно воспроизводиться плавно и без всяких тормозов. Если это не так, то именно поэтому мы и говорим об этом — многие другие приложения тоже демонстрируют такое поведение, не только игры. Пока я могу только рекомендовать вам попробовать посмотреть видео на какой-нибудь другой машине, или просто читать текст.


Проверка, проверка, раз, два, три… Вы должны видеть это видео в плавных 60 fps.

А теперь перейдём к делу. Если вы сталкиваетесь с тормозами, то вероятнее всего это выглядит примерно так:


Вот как выглядят «тормоза при 60 fps». Мы называем этот симптом «кардиограммой».

Да, именно так выглядят «тормоза», даже когда игра работает с 60 fps. Вы могли сталкиваться с чем-то подобным в любой современной игре, и вероятно думали, что «игра не оптимизирована». Так вот, вам стоит пересмотреть свою теорию (о том, что такие тормоза возникают из-за «медленного» рендеринга игры). Если игра «слишком медленная», то это значит, что в какие-то моменты она не сможет достаточно быстро отрендерить один кадр, а монитору придётся заново показывать предыдущий кадр. Поэтому когда мы записываем видео такой игры в 60 fps, то видим «пропущенные кадры». (Это такие кадры, при которых следующий кадр не был отрендерен вовремя, поэтому текущий кадр показывается дважды.)

Теперь снова запустите предыдущее видео с тормозами («кардиограммой»), поставьте его на паузу и нажимайте в проигрывателе YouTube клавишу . (точка), чтобы перемещаться от кадра к кадру. Попробуйте заметить, когда один и тот же кадр показывается дважды. Давайте, попробуйте, я подожду…



Ну как, нашли? Нет? Странно, не правда ли?..

Видео выглядит не плавным, когда смотришь всю анимацию в целом, но когда рассматриваешь покадрово, разрывов нет!

Как такое может быть?


Позвольте мне объяснить более подробно. Вот сравнение идеально плавного видео и видео с тормозами в виде «кардиограммы», воспроизводимые на 1/20 от исходной скорости, чтобы мы могли видеть отдельные кадры:


Сверху правильное видео с 60 fps, снизу «кардиограмма». Воспроизведение замедлено в 20 раз.

Можно заметить две вещи: во-первых, они действительно воспроизводятся с одинаковой частотой — когда сверху есть новый кадр, снизу тоже есть новый кадр. Во-вторых, они по какой-то причине движутся немного по-разному — есть заметный «разрыв» в середине изображения, который становится то более, то менее заметным.

Внимательный зритель может заметить и ещё одну любопытную деталь: нижнее — тормозящее — изображение — которое считается «медленным»… на самом деле «опережает» правильное. Странно, правда?

Если мы посмотрим на два соседних кадра и их тайминги (заметьте, что во всех показанных мной видео были точные таймеры (с точностью 1/10 000 секунды), то можем заметить нечто очень интересное: первые два кадра идеально синхронизированы, но третий…

image

Шесть идущих друг за другом кадров из видео с точными таймингами. Верхние — правильные, нижние — с «кардиограммой».

…на третьем кадре мы видим, что дерево в «тормозящем» видео значительно опережает свою копию из правильного видео (обведено красным). Также можно заметить, что на этот кадр, похоже, ушло больше времени (обведено жёлтым).

Постойте… если видео «медленнее», и на кадр «ушло больше времени», то как он может опережать правильный?

Чтобы разобраться в этом, вам нужно понять, как в наше время игры и другие трёхмерные интерактивные приложения реализуют анимации и рендеринг. (Опытные разработчики должны простить меня за то, что я надоедаю им с очевидными вещами, но мне нужно быть уверенным, что текст смогут понять все читающие этот текст игроки.)

Краткая история таймингов кадра


Давным-давно, в далёкой-далёкой галактике… Когда разработчики создавали первые видеоигры, они обычно подстраивались под точную частоту кадров, с которой работает дисплей. В регионах NTSC, где телевизоры работали при 60 Гц, это означало 60 fps, в регионах PAL/SECAM, где телевизоры работали при 50 Гц, это означало 50 fps. Они даже и думать не могли о какой-то возможности «пропуска кадра».

Большинство игр было очень вылизанными и упрощёнными концептами, работавшими на конкретном оборудовании — обычно на аркадном компьютере, или на "домашнем микрокомпьютере", наподобие ZX Spectrum, C64, Atari ST, Amstrad CPC 464, Amiga и т.д. По сути, разработчик создавал дизайн, реализовывал и тестировал игру под конкретную машину и конкретную частоту кадров, и был на 100% уверен, что она никогда не пропустит ни кадра.

Скорости объектов тоже хранились в единицах «кадров». Поэтому говорили, не на сколько пикселей в секунду должен двигаться персонаж, а на сколько пикселей за кадр. Известно, что в Sonic The Hedgehog для Sega Genesis скорость вращения, например, была равна 16 пикселям за кадр. У многих игр даже были отдельные версии для регионов PAL и NTSC, в которых анимации вручную рисовались специально под 50 fps и 60 fps. По сути, запуск при любой другой частоте кадров даже не рассматривался.

Когда игры начали работать на более разнообразных машинах — в частности, на PC с расширяемым и заменяемым «железом» — разработчики больше не могли знать, с какой частотой кадров теперь будет работать игра. Дополните это тем фактом, что игры стали более сложными и непредсказуемыми. Самыми выдающимися в этом плане стали 3D-игры, отличавшиеся разнообразием сложности сцен, иногда даже зависящей от игрока. Например, всем нравится стрелять в бочки с топливом — при этом происходит огромный взрыв, красивые эффекты… и неизбежная просадка кадров. Но здесь никто не против пропуска кадров, потому что это так интересно.

Поэтому было очень сложно предсказать, сколько займёт симуляция и рендеринг одного кадра. (Стоит заметить, что на современных консолях «железо» по-прежнему неизменно, но сами игры всё равно часто непредсказуемы и сложны.)

Если мы не можем быть уверенными, при какой частоте кадров будет работать игра, нам приходится измерять текущую частоту кадров и постоянно адаптировать физику и скорость анимаций игры. Если один кадр занимает 1/60 секунды (16,67 мс), а персонаж бежит со скоростью 10 м/с, то в каждом кадре он перемещается на 1/6 метра. Но если кадр перестаёт занимать 1/60 секунды, а вместо этого внезапно начал занимать 1/30 секунды (33,33 мс), то надо начать перемещать персонажа на 1/3 метра (в два раза «быстрее») за кадр, чтобы на экране он продолжал двигаться с кажущейся постоянной скоростью.

Как же игра это делает? По сути она измеряет время в начале одного кадра, а затем в начале следующего и вычисляет разность. Это довольно простой способ, но он очень хорошо работает. То есть простите, он работал хорошо. В 90-х (вспомните фразу «35 fps считались приличным значением для серьёзных сетевых боёв» из начала статьи), людей более чем устраивал этот способ. Но в то время графическая карта (не забывайте, их даже ещё не называли GPU) была очень «тонким» элементом «железа», и попаданием объектов на экран непосредственно управлял основной ЦП. Если в компьютере не было 3D-ускорителя, процессор даже сам отрисовывал эти объекты. Поэтому он точно знал, когда они появятся на экране.

Что происходит сегодня


Со временем у нас появились более сложные GPU, и они становились всё более и более "асинхронными". Это значит, что когда ЦП отдаёт GPU команду отрисовать что-то на экране, то GPU просто сохраняет эту команду в буфер, чтобы ЦП занимался своими делами, пока GPU выполняет рендеринг. В результате это привело к тому, что когда ЦП сообщает GPU, что «это конец кадра», GPU просто сохраняет сообщение как ещё один фрагмент данных. Но он не относится к нему как чему-то особо срочному. Да и как он может — ведь ему по-прежнему нужно обрабатывать часть из ранее переданных команд. Он покажет кадр на экране, когда закончит всю работу, которую ему дали раньше.

Поэтому когда игра пытается вычислить тайминги, вычитая метки времени начала двух кадров, то актуальность этого, грубо говоря… весьма сомнительна. Давайте вернёмся к нашему примеру из коротких видео. У нас есть эти кадры, где камера перемещается вдоль деревьев:

image

Шесть идущих друг за другом кадров из видео с точными таймингами. Верхние — правильные, нижние — с «кардиограммой».

Теперь вспомните то, что я говорил о таймингах и перемещениях. В первых двух кадрах тайминг кадра равен 16,67 мс (то есть 1/60 секунды), и камера движется на одну и ту же величину и сверху, и снизу, поэтому деревья синхронизированы. На третьем кадре (внизу) игра увидела, что время кадра равно 24,8 мс (что больше 1/60 секунды), поэтому она думает, что частота кадров снизилась и торопится переместить камеру чуть дальше… только для того, чтобы обнаружить, что тайминг четвёртого кадра составляет всего 10,7 мс, поэтому камера движется здесь чуть медленнее, и деревья снова более-менее синхронизируются. (Синхронизация восстановится полностью только спустя два кадра.)

Здесь происходит следующее: игра измеряет то, что она считает началом каждого кадра, а эти тайминги кадров иногда по разным причинам колеблются, особенно на такой высоконагруженной многозадачной системе, как PC. Поэтому в некоторые моменты игра думает, что не успевает обеспечить 60 fps, и в какие-то моменты генерирует кадры анимации, рассчитанные на меньшую частоту кадров. Но из-за асинхронной природы работы GPU он на самом деле успевает обеспечить 60 fps для каждого отдельного кадра этой последовательности.

Именно это мы воспринимаем как тормоза — анимация, сгенерированная под изменяющуюся частоту кадров («кардиограмму») на самом деле отображается с правильной постоянной частотой кадров.

То есть, по сути, здесь нет никакой проблемы — всё действительно работает плавно, просто игра об этом не знает.

При этом мы возвращаемся к началу статьи. Наконец обнаружив причину проблемы (на самом деле, это иллюзия проблемы — ведь её на самом деле нет, так?), вот что мы сделали для проверки:


Сначала мы наблюдаем «кардиограмму», а затем используем небольшой трюк, чтобы избавиться от неё.

В первой части видео вы с самого начала можете увидеть проблему с «кардиограммой». Затем мы изменяем «магическую» опцию, после чего всё становится идеально плавным!

Что же это за волшебная опция? В Serious Engine мы называем её sim_fSyncRate=60. Если говорить простыми словами, то это значит «полностью игнорировать все эти заморочки с таймингами и притвориться, что мы всегда замеряем стабильные 60 fps». И благодаря этому всё работает плавно — просто потому, что всё и так работало плавно! Единственная причина, по которой всё выглядело тормозящим — это ошибочные тайминги, используемые для анимации.

И на этом всё? Достаточно сделать так и всё станет замечательно?

Неужели решение настолько простое?


К сожалению — нет. Это всего лишь тест разработчиков. Если мы перестанем замерять частоту кадров в реальных ситуациях и просто будем предполагать, что она всегда равна 60, то когда она упадёт ниже 60 — а на PC она рано или поздно обязательно упадёт по тем или иным причинам: ОС запустит какой-нибудь фоновый процесс, включится экономия энергии или защита от перегрева GPU/ЦП… кто знает — то всё замедлится.

Итак, если мы изменяем частоту кадров, то возникают торможения, если нет — то всё в какие-то моменты может замедляться. Что же нам делать?

Реальное решение заключается в том, чтобы измерять не начало/завершение рендеринга кадра, а время отображения картинки на экране.

Как же нам сообщить игре, что изображение кадра уже показывается на экране? Вы можете удивиться, узнав это — но на сегодняшний день такого способа нет!

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

Что дальше?


Но не волнуйтесь, всё не так мрачно. Многие люди в графической экосистеме активно работают над реализацией поддержки правильного тайминга кадров для разных API. Для Vulkan API уже есть расширение под названием VK_GOOGLE_display_timing, которое продемонстрировало свою полезность в реализации proof of concept. Однако оно доступно только для ограниченного ассортимента оборудования, в основном на Android и Linux.

Уже ведётся работа по созданию аналогичных и более качественных систем для всех основных графических API. Когда она закончится? Сложно сказать, потому что проблема лежит довольно глубоко внутри различных подсистем ОС.

Однако я заверяю вас, что Croteam безустанно работает над тем, чтобы эта проблема была решена как можно скорее, и все участники экосистемы интерактивной графики понимают и поддерживают наши усилия.

Мы стремимся сделать это решение доступным для более широкой аудитории, и когда это случится, мы подготовим апдейт The Talos Principle с реализацией этой функции.

Различные помехи и другие подробности


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

«Композитор»


image

Эффект матового стекла? Да, для него нам определённо нужен композитор. Он просто-таки необходим, правда?

За кулисами со всем этим связан концепт под названием «композитный менеджер окон», или композитор. Это система, существующая теперь во всех ОС, которая позволяет окнам быть прозрачными, иметь размытый фон, тени, всплывающие поверх окна Skype и т.д. Композиторы даже могут отображать окна в 3D. Для этого композитор перехватывает управление над последним этапом создания картинки кадра и решает, что ему сделать с ней, прежде чем она попадёт на экран монитора. Это ещё больше всё усложняет.

В некоторых ОС композитор можно отключить в полноэкранном режиме. Но это не всегда возможно, а даже если и возможно — то разве можно запретить запускать игру в оконном режиме?

Управление питанием и тепловыделением против сложности рендеринга


Мы также должны учитывать, что современные ЦП и GPU не работают с фиксированной частотой, а имеют системы, изменяющие их скорости в соответствии с нагрузкой и температурой. Поэтому игра не может просто предполагать, что GPU и ЦП будут иметь одинаковую скорость в каждом кадре. С другой стороны, ОС и драйверы не могут ожидать, что у игры в каждом кадре будет одинаковый объём работы. Чтобы учесть это, необходимо разработать сложные системы для общения этих двух сторон.

А разве мы не можем просто…


Скорее всего нет. :) Обычно измерение времени GPU считается альтернативой таймингам дисплея. Но оно не учитывает наличие композитора и тот факт, что ни один из таймеров рендеринга GPU на самом деле не синхронизирован напрямую с обновлением дисплея. Для идеальной анимации нам абсолютно точно нужно знать время отображения изображения, а не время завершения рендеринга.
Поделиться публикацией

Похожие публикации

Комментарии 268
    0
    А разве мониторы с поддержкой AMD FreeSync и Nvidia G-Sync не решают эту проблему?
    И раз уж такая тема, то что выбрать?
      0
      Только что прочел несколько статей в интернете.
      Есть ещё технология Nvidia Fast Sync. Для него не нужно специального монитора.
      Так как нужна удвоенная часта кадров. Если монитор у вас 60 Герцовый, то FPS в игре должно быть не меньше 120.
      Но это само собой работает только на мощных современных видеокартах и процессорах.
        0
        Для режима «быстрый» нет ограничений по fps. Суть режима в том, что кадры, превышающие частоту дисплея, просто не отображаются — это написано в настройках драйвера.
          0
          это не решает проблему шаттеринга потому что мы не теряем кадры и *синк ничего с этим делать не будет, но это возможно поможет если мы скажем игре что всегда рисуем только 60 в случаях когда кадры всё-таки просядут, но это не точно… возсожно мы получим задержку анимации, что не приемлемо.
        +3
        Статья про другое)
        AMD FreeSync и Nvidia G-Sync — это по сути аппаратный vsync
          0
          Разве? Где там вообще какой-либо sync? Отрисовали кадр — передали на дисплей, где там вообще синхронизация? С чем синхронизируемся?
            0
            Это вы про к чему?
              0
              Это я к тому, что мне лично что FreeSync, что G-Sync видятся вообще асинхронными (ну понятно в определенных границах). Нет там какой-то внешней синхронизации.
          0
          У меня FreeSync, и я всё равно вижу подлагивания тормоза на 60p видео.
            0
            Естественно, потому что это видео — весь v-sync сделан «до нас», фрисинк с ним уже ничего не может сделать — максимум переключить режимы монитора для точного воспроизведения 24/50/60 к/с
            0
            FreeSync и G-Sync нужны исключительно для избавления от «рваных кадров» (tearing) путём синхронизации частоты обновления монитора с частотой кадров рендеринга GPU. Данную проблему это никак не решает, потому как тут именно GPU выдает кадры с различными промежутками времени, хотя в среднем и получаются необходимые 60 кадров, но выглядит картинка плохо. Мониторы с FreeSync и G-Sync будут подстраиваться под эти «статтеры» и выдавать все тоже дерганное изображение, ни на что не влияя.
              –1
              Ещё как влияя — vrr позволяет выводить кадры не привязываясь к конкретной частоте обновления монитора и избавляя от pull-up/pull-down преобразований к фиксированным 60гц (или 75/120, смотря какой монитор)
              GPU выдает кадры с различными промежутками времени — и монитор показывает кадры с различными промежутками времени
                0
                Ещё как влияя...

                GPU выдает кадры с различными промежутками времени — и монитор показывает кадры с различными промежутками времени

                Эти два высказывания противоречивы. Второе верно, монитор перестает влиять на частоту обновления и отображает только готовые кадры с GPU, которые в данном случае имеют существенный разброс времени рендеринга и делают картинку дерганой.

                Еще раз, переменная частота кадров монитора не решает никаких проблем с рендерингом, она только устраняет разрыв кадра путем синхронизации обновления с GPU.
                  0
                  Противоречия здесь нет.
                  Прыгающие фреймтаймы никуда не деваются, только вот без VRR их пытаются запихнуть в фиксированные для 60гц 16.7мс, что во многих случаях значительно усугубляет проблему.
                  Фрисинк не панацея и от статеров не избавит, только вот визуально такое дерганное изображение с фрисинком и без — две большие разницы.

                  А вот от просто проседающего фпс (не статтеров) — фрисинк действительно панацея. Зачем резать фпс до 30, когда система выдает относительно стабильные 45? А зачем резать до 60, если система выдаёт все сто?
              0

              Если я правильно понял суть проблемы, эти технологии не могут решить проблему.
              Приложение (игра) не получают реальных данных о том, сколько рендерился кадр и сколько он отображается, чтобы оно могло точно просчитать следующий кадр.

              –1

              Простое решение есть — собрать машину на порядок мощнее, чем требуется, поставить игровым процессам самый высокий приоритет, отрубить все энергосберегайки, отключить предсказания о которых говорится в статье, и вуаля.
              По большому счету в древних аркадах поэтому проблем и не было — все процессорное время пользовалось игрой и процессор работал со стабильной частотой.
              Да, получается дорого и неэкологично, но для игровых компьютеров, я полагаю, вполне решение. Хотя и выглядит страшненько :)

                +2
                Это не простое решение, а костыли. Всё равно что выкинуть из машины всё лишнее, чтобы она просто ехала.
                  0

                  Иногда так и есть. Сталкивался с ситуацией, когда загруженный седан (атмосферник, 1.5) глох при попытках заехать в горку (крутую). Пришлось отключить кондиционер.

                    0
                    Передачу пониже пробовали включать? Такой же автомобиль, только с автоматом. При заезде на очень крутую горку в Адыгее при нажатой тапке в пол стояла вторая передача, километров 70 в час скорости и нулевое ускорение. Вся моща уходила на подъём ))
                      0
                      На второй глох, на первой можно наверное было заехать.
                0

                Не понял. Как это — мы не можем узнать, когда кадр отображён? Разве момент привязки — не первый же Vertical Retrace после завершения рендеринга?

                  +2
                  Его надо знать до начала построения кадра, вот в чём загвоздка.
                    +2

                    Это да. Но не вижу, как тут могут помочь какие-то API: не могу представить себе системный вызов, позволяющий заглянуть в будущее.


                    Интересно, кстати — насколько быстрее (в типовой игре) рендерится кадр более низкого разрешения? Можно ли рендерить в двух разрешениях, и если мы не успели отрендерить нужный кадр в высоком — отображать в низком? Или же (но тут придётся поизвращаться) отображать афинную трансформацию предыдущего кадра (просто привязав его по нескольким точкам к текущему — чтобы "вздрагивал" в этом случае не весь кадр, а только подвижные объекты)?

                      0
                      Есть пример github.com/KhronosGroup/Vulkan-Tools/blob/master/cube/cube.c
                      Проблема в том что swapBuffers может висеть довольно долго и реальное отображение будет неизвестно когда в этом промежутке, это не обязательно конец swap+glFinish и подобному. Вот это расширение позволяет узнать когда же оно реально было. В будущее никто не заглядывает, просто учитываешь это при генерации следующего кадра. Тут конечно еще может быть время пока кадр дойдет до монитора, но оно обычно уже постоянное и на «stutter» уже не влияет.
                        –1
                        Технология динамического разрешения применяеться например в Path of Exile. На слабом железе работает не так хорошо как хотелось бы, а на мощном оно и не надо.
                          +1
                          0
                          В VR шлемах так делается, на уровне драйвера. Если движок не успевает нарисовать кадр, используется предыдущий, с хитрой деформацией в соответствии с текущим положением шлема. У них в железе ещё и четкая синхронизация сделана, в окулусе кажется есть фотодатчик в углу дисплея, чтобы прям реальное время отображения измерять (photon time).
                      0
                      Разве нельзя померить время рендеринга кадра и если немного убегает вперед картинка, то немного позже ее вывести?
                        0
                        Как я понял — убегает вперёд не кадр (он показывается вовремя, 60 кадров в секунду), а картинка в ней. Т.е. это рендер игры просчитывает будущее для объектов и рисует на текущий стабильный кадр.
                          0
                          нет, тогда будет другая ещё большая проблема мучить — управление станет «неотзывчивым»
                          +8
                          А разве мы не можем просто…

                          Можно просто. Если замеряемый fps около 60 то использовать указанный костыль, если видим что fps реально не успевает — выключаем костыль, действуем как обычно. Это, конечно, не идеально, но поскольку на уровне API решений нет, пока так сойдет…
                            +3
                            Будет накапливаемый рассинхрон. Особенно онлайн-игроки вам передадут пламенный привет.
                              0
                              При выключении костыля синхронизация восстанавливается, для этого и проверяется условие.
                                0
                                Сделать ключевые кадры для сброса, раз в минуту например.
                                  0
                                  Да, только не раз в минуту, а по условию что «убежало» больше чем на 1-2 кадра
                                    +1
                                    И картинка будет дёргаться на каждом таком кадре. За что боролись?
                                      0
                                      Ну это будет только если фпс ниже 60-ти в следствии каких-то временных факторов, то-есть во все остальное время будет жесткое ограничение таймингов. Я так вижу, могу ошибаться.
                                        0
                                        Вот на счёт «я так вижу» кстати можно поспорить.
                                        На замыленный взгляд разработчика (у которого в голове «да от… тесь от меня») оно может быть вот прям почти нормально. Но именно на взгляд.
                                        Из опыта: берём два одинаковых компа или ноутбука, ставим рядом, делаем им идеальную сеть, запускаем отыгрывать один и тот же сценарий.
                                        На взгляд они вполне могут показывать одно и то же, ну, почти.
                                        Но если включить звук — всё сразу становится понятно. На слух даже 1/100 рассинхрона моментально чувствуется. За 1/10 хочется убить.
                                          0
                                          Но если включить звук — всё сразу становится понятно. На слух даже 1/100 рассинхрона моментально чувствуется. За 1/10 хочется убить.

                                          Вы когда в комнате разговариваете, то у вашего голоса с отраженным от стен эхом рассинхрон 1/100, и ничего.

                                            0
                                            Я вот играю на пс подключенным к Аймаку в качестве монитора, так как второй монитор некуда ставить, а к аймаку подключен через USB 3.0 внешнюю карту захвата ( люблю Эппл). Так вот хотя эта карта и передает 1080p при 60 fps задержка таки присутствует 1/70 — 1/100 примерно. Больше всего её видно на рабочем столе при движении мышью. А вот в играх, даже динамических и «задержко-зависимых» типа PUBG или Warthunder она практически не ощущается. Парадокс.
                                              0
                                              А вот в играх, даже динамических и «задержко-зависимых» типа PUBG или Warthunder она практически не ощущается. Парадокс.

                                              Да никакого парадокса, просто задержка там сильно больше, чем 1/100, вот и все.

                                                0
                                                Попробуйте сравнить задержку с steam in-home streaming/nvidia moonlight/amd relive
                                                  0
                                                  Мил человек, ты просто гений! Спасибо за наводку! Moonlight полностью устроил: 4К, 60фпс, низкая задержка. Теперь как белый человек играть буду =) Спасибо!
                                                    0
                                                    Не за что, рад был помочь и надеюсь никаких артефактов сжатия не будет.
                                                    Ну и на будущее про консоли добавлю — на PS4 есть remote play c аппаратным кодированием 720p 60fps, на Ps4Pro уже 1080p 60fps, без HDR. На Xbox One это тоже есть, а вот switch пока обделён — хотя это и неудивительно, свитч легче взять целиком. Вдруг пригодится
                                      0
                                      Почему? Это же примерно то же самое, что делает adaptive v-sync? Или нет?
                                    +5
                                    А нельзя использовать метод скользящей средней вместо измерений частоты на каждом цикле или полного игнорирования?
                                      +1
                                      А чем это поможет? Представьте что у вас swapBuffers только из-за синхронизации выполняется от 0мс до 16мс (заранее неизвестно сколько, этого вполне достаточно для stutter) + работает еще неизвестно сколько, если перед этим не было glFinish + общая нагрузка меняется немного от кадра к кадру + вы не знаете когда реально при работе swapBuffers произошло отображение. Это может уменьшить эффект, но реальную проблему этим не решить. Надо знать когда именно было отображение в swapBuffers + надо иметь возможность сообщить лучшее время отображения следующего кадра (мы же исходя из всех расчетов передвинули куда-то геометрию, где предполагаем след кадр будет отображен, но драйвер об этом ничего не знает), вот теперь это можно сделать используя VkPresentTimesInfoGOOGLE.
                                        0
                                        Почему вы не используете glFinish? Один фиг рендер в отдельном потоке, так что подождать пока кадр отрендерится и потом только продолжать пихать в GPU — вполне норм. Тем более, что лока на заполнение буфферов всё равно в этот момент нет и можно подготавливать следующий кадр, пока ждем финиш.
                                          0
                                          Я потому про него и написал, glFinish + swap получаем теоретическую неопределенность только 0-16мс с синком. Но принципиальным это не является, мы ведь считаем за время отображения конец swap. Если он таковым не является по неизвестной нам причине, вот возникло у драйвера еще работы на 5мс после свопа из-за архитекрутных/драйверных особенностей, то привет. Хорошо если оно постоянное, а если переменное (например переодическое GC запустили) — беда. Вот в статье как раз описано: выброс до 24.8мс на самом деле фейковый, если его принять за 16.6 — то все плавно, то-есть время отображения было 16.6, а 8.2мс драйвер занимался неизвестно чем. Плюс стратегий компенсации может быть множество, если мы хотим что-то предсказать и компенсировать, указать желаемое время отображения опять же без расширения способа нету.
                                      0
                                      Похожая проблема есть в Unity. Если собрать простой проект, где движется куб то можно заметить как он немного дергается.
                                      Решается похожим способом:
                                      Application.targetFrameRate = 60
                                        0

                                        Такой баг сложно воспроизвести. Скорее всего вы двигаете куб на константное значение в методе update, а надо константное значение умножать на Time.deltaTime. Тогда плавность будет нарушена только в очень редких случаях, как описано в статье

                                          0
                                          Вот она, квинтэссенция статьи, иллюстрирующая механику возникновения подобных проблем на пустом месте. Не пересчитывайте состояние мира в Update(), она привязана к фреймрейту. И не используйте deltaTime. Для этого есть FixedUpdate(). В Update вам нужно подготовить сцену для следующего кадра, в данном случае выставить в GameObject координаты объекта из последнего расчёта мира.
                                            0
                                            Если сделать вот так, то объект будет двигаться плавно, за исключением случаев, описанных в статье. По факту — выявить такие случае на этапе разработки на компьютере разработчика практически не реально.
                                            Vector3 velocity;
                                            void Start() {
                                            velocity = transform.forward;
                                            }
                                            void Update() {
                                            transform.position += velocity * Time.deltaTime;
                                            }

                                            И как же, по вашему, может быть решена проблема, описанная в статье, используя методы FixedUpdate? По моему мнению, проблема, описанная в статье, на данный момент, нерешаема в общем виде. Только костылями. Если вы придумали решение, будь-те любезны показать пример кода.
                                            Вообще я разрабатываю сетевые игры. Например RTS стратегию. У меня координаты смещения объектов вычисляются вообще в отдельном потоке или приходят по сети. А в Update идет интерполяция между старым и новым положением. В любом случае, transform.position должен меняться в методе Update и всегда по какой-то формуле, зависимой от времени. Только так получается достигнуть плавного движения. Буду рад увидеть код с другим решением.
                                              0
                                              По формуле, зависимой от времени в FixedUpdate(), с источником времени, не привязанным к фреймрейту, в Update() только присваивание того, что насчиталось там. По моему мнению, проблемы не существует, только от подобного подхода с привязкой к фреймрейту, что как подмечено в статье, было нормально в 90-е, но не сейчас. Конечно, проседание времени кадра сюда не относится, это вопрос оптимизации. В итоге будет плавающая задержка между фактическим отображением кадра и текущим состоянием мира, но она колеблется в слишком небольших пределах, чтобы на что-то влиять, эффектов торможения от этого не должно быть.
                                                0
                                                FixedUpdate() как правило вызывается реже, чем Update. К примеру на один FixedUpdate у вас будет вызвано 5 раз Update, в этом случае у вас 5 кадров объект будет со старыми координатами, посчитанными в FixedUpdate. Потом вызовется FixedUpdate, и изображение дернется. Ну или даже если вы сделаете частоту вызова FixedUpdate чаще, чем в Update, все равно, будет разсинхрон, который приведет к дерганию.
                                                В итоге будет плавающая задержка между фактическим отображением кадра и текущим состоянием мира, но она колеблется в слишком небольших пределах, чтобы на что-то влиять, эффектов торможения от этого не должно быть.

                                                Вы это пробовали сами написать? У меня всегда в таких случая были только лаги. Так можно делать, если в Update пихать интерполяцию между старыми и новыми значениями, посчитанными в FixedUpdate(), но и то, объект то будет ускоряться то замедляться.
                                                Рассмотрим пример. Пусть частота FixedUpdate() и Update () примерно равна. В FixedUpdate() мы изменяем координату на один. x+=1; В Update отображаем эту координату. За 9 итераций FixedUpdate выводит значение x {1,2,3,4,5,6,7,8,9}, Update вызывается без синзронизации, поэтому иногда он будут запаздывать, иногда брать значение раньше, чему нужно, может получиться к примеру {1,1,3,4,4,6,6,8,9} То есть иногда объект будет слишком спешить, иногда ждать.
                                                  0

                                                  Там даже есть delta именно для FixedUpdate.
                                                  На самом деле странное решение… перемещение объектов и камеры будет иметь ниже FPS чем у всяких эффектов при том что фреймрейт може быть высокий.

                                                  0
                                                  Нет, из-за разницы между реальным таймом и фиксированным наоборот будут прыжки туда-сюда в отображении. Или вообще времени на 1 фиксед апдейт по каким либо причинам может не хватить и тогда картинка поплывёт. Кроме того инпут от пользователя приходит в реальном времени и его нужно обрабатывать как раз моментально, иначе управление будет «деревянным» что намного хуже для игр.
                                              0
                                              Данный баг воспроизвести довольно просто в любых версиях Unity. Добавьте к примеру куб на сцену и двигайте его как вам удобно: в Update с Time.deltaTime, через AddForce или FixedUpdate. Вы увидите как он дергается. Многие просто этого не замечают, отказываются видеть и верить и этот косяк присутствует даже в топовых мобильных играх.
                                                0
                                                Понятно что какие-то дерганья всегда есть, все работает с погрешностью. Но я, к примеру, не способен увидеть такие лаги, пока они не достигают критических значений. Может просто у вас зрение позволяет замечать больше, чем у большинства людей.
                                                  0
                                                  Тут еще дело в опыте. И я не говорю про игровой в целом, а про очень хорошо оптимизированные игры. Поиграв много в игры которые идеально себя ведут и очень отзывчивы, потом подобные мелочи очень в глаза бросаются.
                                                    0
                                                    Играли в Rage?
                                                      0
                                                      Играл. Но не долго. Читал очень много комментариев про проблемы с подгрузкой текстур и лагах при вращении камеры, но на удивление у меня все было нормально.

                                                      А к чему вопрос?
                                                        0
                                                        Читал, что это самая стабильная в плане частоты кадров игра.
                                                    0
                                                    Увы, я даже немного слеповат.
                                                    В свое время продюсер погонял насчет того, что дергается картинка при хорошем FPS. Потом выяснилось, что если Unity принудительно не ограничивать в кадрах, то колебания между 80-100 кадрами в секунду очень плохо влияет на плавность картинки.
                                              0

                                              Кстати, посмотрел ещё на картинку с таймингами фреймов, подумал… Но ведь бредовые же тайминги! 24.8 — ещё туда-сюда (допустим, картинка отображалась в течение двух кадров, значит, "центр масс" попадёт на середину между ними, смещение в полкадра. А 10.7 и 14.3 — это какой-то болезненный бред. Не может такого быть. Все числа должны быть кратны 16.6 (если считать по моменту отображения кадра), на крайняк 8.3 (если считать по "серединам" и кадры отображаются разное время).

                                                +1
                                                Это ведь время рендеринга кадра, а не вывода
                                                  +2

                                                  Не-не-не, это не время рендеринга кадров (оно не может быть 16.6 — слишком много для 60 fps), это, насколько я могу судить, разница "физических" времён кадров (т.е. на какое время обсчитывается игровой мир в каждом кадре)

                                                    0
                                                    Почему не может? 16.(6) мс — это как раз время кадра для 60 фпс. Просто разделите 1 на 60, чтобы убедиться…
                                                      +1

                                                      Именно поэтому. Нужен запас времени. А если обсчёт кадра занимает примерно 1/60 секунды — то даже крохотная задержка приведёт к тому, что мы не успеем вывести его вовремя, и выведем ещё на 1/60 секунды позже. Т.е. у нас половина кадров будет по 1/60 секунды, а половина по 2/60, гарантированное дрожание картинки.

                                                        0
                                                        Нет, ибо, многопоточность и асинхронность. Они же и косвенная причина статьи.
                                                          0

                                                          т.е. в старом добром однопоточном рендринге аля GL2 эту проблемму можно было бы избежать?

                                                +5

                                                эммм. помнится ещё в лохматые года было ж придумано, что игровой движок существует со своим "фпс", которым рассчитывается вся логика, а отображение идёт отдельно от него по принципу "как успеет". это ведь отображение только. там можно дропать кадры, перерисовывать/актуализировать когда угодно. это ж дурь полная, если физика, например, завязана на фпс видеокарты.
                                                ну и в сетевых всех играх так 100% — ведь не может же течение игрового времени для всех игроков считаться из усреднения их фпс?

                                                  +1
                                                  Не знаю, насколько лохматыми были конец 90-x, но физика движка Quake 3 (id Tech 3) зависела от частоты кадров, хотя графика обрабатывалась на GPU. И в сетевых играх тоже.
                                                    0
                                                    Эмм, в q3 есть sv_fps, которая определяла частоту симуляции.
                                                    Ну и в 90-х, физика была попроще. От фпс мало зависело движение объектов.
                                                      0
                                                      sv_fps есть, только толком его никто и никогда не использовал. Геймеры и не понимали особо его сути, зато всем и обязательно нужно было иметь стабильные 120fps, которые ставились командой com_maxfps. А если частота кадров скакала, то были неприятные проблемы — в частности, без стабильных 120 фпс нельзя почти нельзя перепрыгнуть с мостика на рейлган на dm6 в osp mode.
                                                        0
                                                        Это уже, скорей всего связано с частотой опроса инпута, а не с физикой.
                                                          0
                                                          с мостика на рейлган можно прыгать с любой вменяемой частотой кадров, там проблема в правильных движениях, чтобы нужную скорость набрать.

                                                          а вот прыжок на t2 с лесенки на шарды (и в тысяче других подобных мест) действительно при фпс ниже 120 не удавался по высоте.
                                                            0
                                                            Скрытый текст
                                                            фанат defrag mode? :D
                                                          0
                                                          в 90-х, физика была попроще. От фпс мало зависело движение объектов

                                                          Нет, движок Quake при FPS выше ста начинал ощутимо глючить в расчётах физики позволяя использовать его багофичи для всяких сложных продвинутых трюков.
                                                            0
                                                            Извиняюсь за занудство, но это не совсем так. Насколько я понимаю, это не совсем глюки, а ошибки округления. И не при «выше 100 фпс», а при некоторых магических значениях — вроде бы 43, 72, 120 (могу ошибаться — давно это было). Подбиралось то фпс, которое стабильно могла обеспечить система. Это давало увеличенную высоту прыжка. Вплоть до того, что с неправильным фпс невозможно было запрыгнуть на некоторые объекты типа больших ящиков в RTCW.
                                                              0
                                                              Я в своё время мапил специальный уровень с площадками разной высоты и замерял высоту для каждого из значений FPS. После 500 FPS вообще начинались чудеса и самопроизвольные дисконнекты.
                                                            0
                                                            Также была pmove_fixed, которая отвязывала физику от частоты кадров. Но, как и sv_fps, появилась она далеко не сразу.

                                                            q3 вышла в декабре 99. Почти начало 2000-х.

                                                            Я не сравниваю современные игры с играми прошлых лет. justmara предположил, что зависимость физики от фпс видеокарты — полная дурь, но тем не менее, нечто подобное было.
                                                              0
                                                              зависимость физики от фпс видеокарты — полная дурь

                                                              А если физику считать через CUDA на видеокарте, тогда как?
                                                                0
                                                                зависимость физики от фпс видеокарты — полная дурь, но тем не менее, нечто подобное было.
                                                                Было-было. В Mafia 1 даже непроходимые места из-за этого есть.
                                                                Just like with the Exploding Celeste mission, this subquest is virtually impossible if you own a better hardware which gives a good framerate. But lowering the framerate will reduce the rate of bombs dropping and thus, the probability of your car being hit.

                                                                Еще почитать: pcgamingwiki.com/wiki/Glossary:Frame_rate_(FPS)#Frame_rate_capping
                                                                  –3
                                                                  Мафия — это сугубо синглплеерная игра. Ей можно зависеть от фпс. Это упрощает движок — не надо делать никаких трюков чтобы положить частоту кадров на частоту физики.
                                                                  0
                                                                  pmove_fixed — это в некотором роде чит как и cl_timenudge и его всегда выключали на чемпионатах. Простая проверка скилла — с выключенным pmove_fixed на q3tourney2 было довольно проблематично выпрыгнуть из телепорта сразу на площадку к броне/рокету. С включенным pmove_fixed любой мог так сделать. /ностальгии тред
                                                                0
                                                                В Quake2. На этом был основан трюк с запрыгиванием на некоторые ящики.
                                                                0

                                                                Этот параметр называется tickrate. Он нужен для синхронизации состояний и к плавности картинки отношения не имеет. У недостаточного tickrate-а совершенно другие симптомы. Хороший пример это Battlefield 3 с его 10Hz на старте продаж. На YouTube думаю ещё остались видео с тем как это выглядело.

                                                                0
                                                                Неужели сложно сделать очередь кадров в GPU и выводить их с фиксированным FPS?
                                                                При этом считать движение с фиксированным dt будет немного проще.
                                                                А если CPU/GPU не успевает просчитать кадр, то повторять предыдущий, либо рендерить каждый кадр последовательными приближениями с лимитом на время выполнения.
                                                                  0
                                                                  Так делают, но это ухудшает отзывчивость и всё становится еще хуже.
                                                                  0
                                                                  Ребята, а есть ли какой-то способ сгладить эту проблему на стороне пользователя уже сейчас?
                                                                  Мне бы очень хотелось знать, что я могу сделать, как обычный геймер. Это чертовски актуально, т.к. есть вполне отличные игры, которые «какбы» выдают свои 60fps, однако при этом картинка совсем-совсем не плавная.
                                                                  На данный момент мне немного помогало лишь отключение V-Sync и таким образом разблокировка fps выше 60. Но при этом, как побочный эффект (о котором честно предупреждает Nvidia) появляются всякие разрывы изображения.
                                                                  Можно ещё что-то попробовать? Помогут ли всякие мотиторы с G-Sync & FreeSync?
                                                                    0
                                                                    Можно попытаться в настройках процесса отключить несколько ядер. Если у вас потоков в проце много, конечно. Это может уменьшить средний FPS, но пиков станет меньше. Говорю в теории.
                                                                      0
                                                                      Раньше помогало снижение настроек, но я так понимаю, что всё. Опять же, поговаривают, что в красном лагере с этим получше — можно попросить у кого из знакомых «поиграться».

                                                                      Вообще, помнится, раньше нВидиа умела рендерить с отключенным vSync и без разрывов, но с тех пор она объелась стеройдов и положила качество в жертву скорости. Теоретически, *Sync-и должны помочь — сути их как раз в синхронизации времени вывода с временем рендеринга, так что попробовать можно.
                                                                        0
                                                                        Не обязательно сильно выше 60. Через профили Nvidia например можно под каждое приложение выставить максимальную частоту экспериментально. Мне чаще всего подходит 62 кадра, v-sync принудительно выключаю везде.
                                                                          0
                                                                          Если у вас довольно мощный компьютер, может в какой-то степени помочь тройная буферизация.
                                                                            0
                                                                            G-Sync очень помог. Если кадры скачут, скажем, с 40 до 100, то визуально это действительно незаметно, разрывов изображения нет. Могут ощущаться изменения в отзывчивости (кнопки, интерфейс, клики), но это наверное уже от самих игр зависит.

                                                                            Если fps падает ниже 30, G-Sync отключается, старые добрые лаги возвращаются.
                                                                              0
                                                                              Вы имеете ввиду, что вам помог G-Sync именно в том случае, который описывает автор статьи?
                                                                              Я уточняю, т.к. тут очень специфическая проблема, fps нормальный, с V-Sync всегда железно 60 кадров, ничего не проседает вообще. Однако именно картинка, которую видишь своими глазами, а не на датчиках, совсем не плавная.
                                                                              Автор описал достаточно распространённую проблему, которая встречается много где, много у кого. Есть весьма неудачные в этом плане игры, которые страдают такой проблемой. У других же игр, на том же железе, таких проблем нет вообще.
                                                                              Т.е. достаточно странная ситуация, учитывая, что автор говорит о том, что проблема в первую очередь на стороне производителей видеокарт и драйверов.
                                                                                0
                                                                                Не уверен. Я сужу по WoW, там картинка в движении плавная. The Talos Principle у меня есть, попробую глянуть.
                                                                                  0
                                                                                  Ого! А вот это очень хорошо, т.к. у автора как раз там была эта беда! В идеале глянуть сначала с G-Sync, затем с без него. Но это уже заморачиваться немножко нужно.
                                                                                  Такая же проблема есть ещё в Soma, там её даже искать не нужно, она перманентная.
                                                                                  0

                                                                                  Если я правильно понял суть g-sync (что можем сами сказать монитору, что пора отображать новый кадр) — должен изрядно сгладить проблему. Мы просто не попадём в ситуацию, когда "отстали" (или решили, что отстали) аж на 1/60 или 1/120 секунды — можно же в этом случае просто отобразить кадр чуть-чуть позже.
                                                                                  Но полностью проблему (что для максимального fps нам надо заранее знать время обсчёта кадра) не уберёт.

                                                                                    0

                                                                                    G-sync так же проблему не решает! Проблема не в том, когда монитор отобразит отрендеренный кадр(этим занимается g-sync), но и что — для какого конкретно ближайшего будущего подготовленный кадр будет отображаться. Есть шанс в 50%(если успели до дедлайна) что монитор должен будет ждать дополнительные несколько миллисекунд, что бы начать поворачивать пиксели в точно расчитанное время, а не как быстрее. Это должно так же повысить плавность.

                                                                                      0
                                                                                      Так же включая лимитер/vsync, мы только повышаем вероятность уложиттся в дедлайн (который мы сами расчитали заранее до начала рендера) до отображения. В случае же если мы его совсем провалили, последний кадр нужно ВЫКИНУТЬ без отображения совсем, тк лучше никак чем поздно. Есть также возможность выключить подсетку дисплея во время пропуска, что бы мозг сам дорисовал пропуск, ака lightboost, но который включается только когда надо, а не всё время и между кадрами.
                                                                                        0
                                                                                        Продолжу, быстрый гуглеж говорит, что среднее время моргания глаза около 40-50 мс, поэтому есть шанс отрендерить аж 2 кадра совершенно незаметно для человека(главное гарантированно хотя бы 1). Черный экран при этом можно симулировать простой заливкой и без выключения подсветки на обычном экране. На 120-144Hz должно быть менее заметно и без какого либо g-sync.
                                                                                        0

                                                                                        Не решает, а смягчает: допустим, мы обсчитывали кадр для момента t, но не успели на пару миллисекунд. С g-sync мы его (если я правильно понял суть технологии) сможем отобразить в момент t+2, без — только в t+16.6.

                                                                                          0
                                                                                          В то же время gsync может отобразить кадр для t в время t-2, тк емо хочется быстрее, а так делать не надо.
                                                                                            0

                                                                                            Зачем/как? Если ему этот кадр отдать в момент t — не сможет. Если отдать в момент t-2 с командой "отобразить в момент t" — "не захочет".
                                                                                            Но, повторюсь — это если я правильно понял суть технологии...

                                                                                  0
                                                                                  монитор со 120фпс?
                                                                                    0
                                                                                    Монитор для стерео-очков поддерживает высокие FPS.
                                                                                      0
                                                                                      Необязательно иметь именно монитор с высоким фреймрейтом, можно начать с того, чтобы отрисовка на gpu происходила значительно быстрее вывода, тогда время «рывка» сократится, и ошибки таймера окажутся за пределами восприятия. Надо понимать, что шина данных «cpu -> gpu -> монитор -> глаза» всегда имеет определённую степень асинхронности, поэтому кратное увеличение частоты обновления на отдельных её участках может сделать картинку значительно плавнее.
                                                                                      0
                                                                                      На нынешнем мониторе можете попробовать nvidia Fastsync/AMD Enhanced sync, но от этой проблемы они не помогут, да и фпс нужен больше герцовки раза в два — отсутствие разрывов и высокий фпс при пониженной задержке ввода. Но вот новый монитор я бы советовал брать сразу с VRR (G-Sync & FreeSync)
                                                                                      G-Sync & FreeSync помогут при нестабильных фреймтаймах и проседающего фпс — крайне полезная штука
                                                                                      –2
                                                                                      Вся суть статьи одним предложением: «Вместо Time.deltaTime используйте Time.fixedDeltaTime». Это для Unity. Уверен что в других движках тоже можно сделать привязку перемещения/анимации к независимому от FPS таймеру.
                                                                                        0
                                                                                        Насколько я понял, тут глубже проблема. Движок считает Time.deltaTime, а потом ОС отправляет этот поток спать на, допустим, миллисекунду. Лишь ПОСЛЕ ЭТОГО движок считывает данные с контроллера (с опозданием на миллисекунду) и вся математика начинает косячить, из-за чего появляются неприятные эффекты.
                                                                                          0
                                                                                          Не выйдет — только если они всегда будут равны — а так не бывает.
                                                                                          В противном случае все объекты, которые передвигаются, будут двигаться со скоростью, зависящей от частоты кадров. В мультиплеере это вообще фиаско.
                                                                                            0
                                                                                            Вот и у меня сразу такая мысль была. Я так и не понял глубины глубин этой «проблемы». 30 лет назад действительно была привязка к частоте кадров, но в современном игрострое за такое по пальцам бьют. deltaTime можно использовать разве что для показа того самого индикатора FPS и только.
                                                                                              –1
                                                                                              Не в fixed проблема. То есть отвязать анимации от рендера — это само собой разумеющееся, но основная проблема в том, что кадр может нарисоваться как через 16мс, так и через 24мс. То есть показан он будет в разное время, и отсюда будут рывки.
                                                                                              0
                                                                                              По большому счету, для сингл-плеера решение все-таки существует: для расчетов использовать не реальное время с последнего кадра, а 1/fps. Конечно же, fps надо считать буквально по количеству кадров, вместившихся в последнюю секунду. Пик как в статье будет полностью нивелирован, а при небольшом «проседании» fps, синхронизация наступит за секунду. Визуально все будет очень плавно и только немного мир замедлится/ускорится.
                                                                                              Можно даже использовать не целую секунду для расчетов, а последние 5-10 кадров, этого обычно достаточно для сглаживания пика. В зависимости от ситуации, среднее или медианное время последних N кадров может дать идеальный результат.
                                                                                                –1
                                                                                                Проведём простую цепочку преобразований: 1/fps => 1 frame / ( N frames per second ) => 1*frame / ( N*frame / deltaTime_1 )
                                                                                                =>1/N * frame/frame * delta_time_1 => 1/N delta_time_1 = delta_time_n

                                                                                                То, что Вы предлагаете — это и есть подсчет времени, просто другое численное выражение( в долях от случайного временного интервала, а не в миллисекундах (тысячных долях от секунды).
                                                                                                  +3
                                                                                                  fps = N/(frame_1_time + frame_2_time +… frame_N_time)

                                                                                                  Считается обычно для некоего разумного числа последних кадров N, потому как для 1 кадра смысла не имеет, для 1000 тоже. Значение 1/fps является средним значением длительности последних N кадров.

                                                                                                  То, что я предлагаю (и что используется уже лет 15 в разных движках для некоторых задач, н-р, в Unigine), это использование плавающего усредненного времени кадра, либо медианного времени кадра, взятые для ближайшего временного интервала.
                                                                                                0
                                                                                                Хороший перевод, спасибо.
                                                                                                  –6
                                                                                                  Лучше лочить фпс через RivaTuner, чуть выше или ниже частоты обновления монитора с использованием FastSync и в целом все получается неплохо.



                                                                                                    +5

                                                                                                    А зачем вообще нужны ка ие-то синхронизации???
                                                                                                    Вот взять идушего человека которого фотографируют с какой-то частотой. Ему нужно знать эту частоту? Нет! Он просто идёт с какой-то скоростью, которая вообще никак не связана с частотой съёмки. А съёмка лишь позволяет заглянуть где он находился через какие-то промежутки времени.
                                                                                                    Если игра будет считать перемещения не от частоты кадров, а по внутреннему таймеру много большей частоты независимо от частоты кадров, а запускать рендер как получится — разве это не решит проблемы?

                                                                                                      +1
                                                                                                      У меня возник такой же вопрос. Если игра будет генерить данные для рендера по своему таймеру, а рендер тред будет забираться всегда последнюю актуальную версию, то по идее такой проблемы быть не должно. Мне кажется всё это идет от привычки всю игру в одном цикле делать: Посчитали игровое состояние -> Отрендерели -> померяли время снова считаем игровое состояние.
                                                                                                        +1
                                                                                                        В этом и суть проблемы, человек идет себе, вы его фотографируете, но если вы потом из фоток склеете видео, то идеально плавным оно будет только в том случае, если вы делали снимки с одинаковым интервалом. Если где-то будет разный промежуток, глаз заметит рывок
                                                                                                          0
                                                                                                          Если бы всё было так просто то проблема бы не решалась выставлением константного deltaTime. Проблем в том что delta между кадрами на самом деле меньше чем фактическая, которую на данный момент измерить нельзя, если рендер будет всегда брать последнюю версию состояния, которая будет считаться с константным dt, то проблема не должна себя проявлять
                                                                                                            0
                                                                                                            Проблема в том что моменты когда рендер берет версию состояния могут сильно отличаться от моментов когда картинка выводится на экран.

                                                                                                            Грубо говоря рендер вначале берет каждую 0.1 секунду данные:
                                                                                                            0.0, 0.1, 0.2, 0.3…
                                                                                                            А потом у нас где-то возникли тормоза на полкадра и следующее чтение случилось когда натикало уже 0.45:
                                                                                                            0.0, 0.1, 0.2, 0.3, 0.45
                                                                                                            При этом в реальности тормоза были только на CPU, а GPU вполне успешно продолжал работать и в «плановый» момент 0.5 затребовал новую информацию о состоянии мира. CPU в этот раз не протормозил и оперативно выдал запрошенное
                                                                                                            0.0, 0.1, 0.2, 0.3, 0.45, 0.5,…
                                                                                                            И все, приплыли, stutter. На экран в момент 0.4 будет показан кадр расчитанный для момента 0.45.
                                                                                                              0
                                                                                                              В этом объяснении я не понимаю одного, каким образом тогда выставление фиксированного dt в случае автора статьи решило проблему?
                                                                                                                0
                                                                                                                Вроде проблема в другом. CPU считал физику 0.0 0.1 0.2 0.3 0.4. GPU отвечал что нарисовал кадр в 0.1 0.2 0.3 0.45. CPU заметил что отрисовка запаздывает и занимает 0.15 а не 0.10. И следующий тик посчитал в 0.6 а не 0.5. И когда GPU пришёл заданными для 0.5 отдал ему данные для 0.6 что и вылилось в опережение кадра.
                                                                                                                  0
                                                                                                                  когда GPU пришёл заданными для 0.5 отдал ему данные для 0.6 что и вылилось в опережение кадра.

                                                                                                                  Вспомнилось «дежа вю — глюк Матрицы» (с)
                                                                                                                  0
                                                                                                                  Потому что у автора моменты времени считаются «по запросу». Физика считается не непрерывно а лишь в дискретные моменты времени. Принудительное выставление моментов на 0.0, 0.1, 0.2, 0.3, 0.4, 0.5 естественно решает проблему.
                                                                                                                    0
                                                                                                                    Именно такое решение и предлагается собственно, двигать мир независимо от рендера, показывать последний актуальный результат в результате пользователь видит мир с небольшой, но постоянной(при отсутствии реальных скачков фпс) задержкой, равной времени рендера кадра.
                                                                                                                      +1
                                                                                                                      Что есть «последний актуальный результат»? В примере приведенном выше это 0.45 а отнюдь не 0.4 просто потому что запрос на получение результата случился чуть-чуть с запозданием и мир успел обновиться раньше чем GPU забрал нужное состояние для очередного кадра.
                                                                                                                      0

                                                                                                                      Так почти везде так и работает. Проблема из статьи — что-то специфичное для каких-то отдельных движков в отдельных играх.
                                                                                                                      Сама идея сперва синхронизировать стейт под фпс, а потом его обратно рассинхиронизировать отдает несколько альтернативной логикой :)
                                                                                                                      Вот где реальная проблема — это видео, т.к. там частота кадров фиксирована и без синхронизации нельзя.

                                                                                                                        0
                                                                                                                        Так и работает это как? Выставлением равномерного шага симуляции от кадра к кадру при неравномерной частоте кадров?

                                                                                                                        Никто стейт не «рассинхронизирует» специально, статья про то что это явление само собой возникает из-за невозможности обеспечить стабильную задержку между определением состояния мира и выводом кадра на экран.
                                                                                                                          +1
                                                                                                                          Так и работает это как? Выставлением равномерного шага симуляции от кадра к кадру при неравномерной частоте кадров?

                                                                                                                          Симуляции вообще ничего не надо знать о кадрах. Она просто работает по своему таймеру. А рендер время от времени выдает, с-но, кадры.
                                                                                                                          Проблемы возникнут только тогда, когда вы захотите обеспечить какую-то конкретную частоту кадров (например, сделаете ограничение в 60 фпс).

                                                                                                                            0
                                                                                                                            Проблема с-но естественным образом возникает из-за того что рендер забирает кадры с неравномерной задержкой (точнее не с той же самой задержкой с которой они показываются). Только и всего. Конкретность частоты кадров здесь совершенно не при чем.
                                                                                                                              0
                                                                                                                              Проблема с-но естественным образом возникает из-за того что рендер забирает кадры с неравномерной задержкой (точнее не с той же самой задержкой с которой они показываются)

                                                                                                                              Это как раз не проблема. Забирает и забирает, фиг с ним, рывков от этого не возникнет.
                                                                                                                              Проблема начинается как раз тогда, когда вы попытаетесь синхронизировать частоту "забора", и для этого подкручиваете таймер самой симуляции. Эти ведь рывки из статьи — это не рывки отображения, это рывки симуляции. Видеокарта успевет рендерить равномерно, но сама симуляция из-за подкрутки становится неравномерной.
                                                                                                                              Если же вы не занимаетесь подкруткой таймера симуляции — то и рывков не будет, т.к. симуляция будет равномерной (если, конечно, она сама не начнет тормозить, но в реальности у нас практически все игры gpu-bound с огроменным запасом)

                                                                                                                                –1
                                                                                                                                Забирает и забирает, фиг с ним, рывков от этого не возникнет.

                                                                                                                                Возникнет. Осознайте уже наконец что данные симуляции забираются рывками, неравномерно

                                                                                                                                Подкрутка симуляции которая так сбивает всех в данной статье — это просто способ не считать симуляцию в тех временных точках где она не нужна. Но проблема никак не связана с этой оптимизацией. Она будет возникать и при идеальной, непрерывной симуляции. Причем там дословно те же самые кадры с рывками будут забираться. Просто еще и куча «ненужных» будет выкидываться.
                                                                                                                                  +1
                                                                                                                                  Возникнет. Осознайте уже наконец что данные симуляции забираются рывками, неравномерно

                                                                                                                                  В рассматриваемом случае они забираются равномерно, но неравномерно происходит сама симуляция.


                                                                                                                                  Подкрутка симуляции которая так сбивает всех в данной статье — это просто способ не считать симуляцию в тех временных точках где она не нужна. Но проблема никак не связана с этой оптимизацией.

                                                                                                                                  Именно с ней она и связана. Из-за подкручивания таймера симуляция становится неравномерной — и когда вы равномерно выводите кадры неравномерной симуляции, то получаете рывки. Если не подкручивать кадры — проблемы просто нет.


                                                                                                                                  Она будет возникать и при идеальной, непрерывной симуляции.

                                                                                                                                  Откуда? Вы перечитайте еще раз пример с разбором из статьи. Кадр выводится за 16.5, но игра думает что он выведен за 24.8. При этом происходит подкрутка симуляции — и вместо того, чтобы через 16.5 сек вывести состояние через 16.5, выводится то состояние, в котором мир находится через 24.8. В результате симуляция мира опережает актуальное время, в которое выводится кадр, на 8.3, игра вам рендерит "будущее".
                                                                                                                                  Если вы ничего не будете подкручивать, то через 16.5 игра выведет ровно то, что там и есть — состояние, в котором находится симуляция через 16.5.
                                                                                                                                  При этом реальный фпс как раз 60 — именно об этом же и идет речь в статье, что фпс не падает, он держится ровно, кадры выводятся равномерно, но это не те кадры из-за того, что в силу подкрутки внутриигровое время симуляции скачкообразно опережает реальное.

                                                                                                                                    0
                                                                                                                                    В результате симуляция мира опережает актуальное время, в которое выводится кадр, на 8.3

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


                                                                                                                                    Если в первом случае вы испытываете "всего лишь" ускорение в 24.8/16.5 ~ 1.5 раза, то во втором кадре время замедляется, вы видите движение в 10.7 вместо 16.5, в итоге сравнительная скорость между двумя последовательными кадрами — 24.8/10.7 ~ 2.3.

                                                                                                                                      0
                                                                                                                                      В рассматриваемом случае они забираются равномерно, но неравномерно происходит сама симуляция.

                                                                                                                                      Неверно. Забираются они неравномерно а симуляция просто подстраивается под этот неравномерный момент забора. Вот выводятся на экран результаты равномерно, но вывод на экран != момент забора данных

                                                                                                                                      Если не подкручивать кадры — проблемы просто нет.

                                                                                                                                      Совсем не подкручивать (грубо говоря забирать данные симуляции с равномерным интервалом) нельзя в силу того что симуляция так или иначе должна синхронизироваться с происходящим на экране, иначе у нас физика начнет зависеть от FPS (больше FPS — быстрее падают объекты и т.д.)

                                                                                                                                      Кадр выводится за 16.5, но игра думает что он выведен за 24.8.

                                                                                                                                      Она так думает потому что прошло 24.8 мс с момента последнего забора данных от симуляции. А не потому что ей так внезапно захотелось. Понимаете теперь? Мы выводим состояние в момент времени «24.8» потому что мы запросили его в момент времени «24.8».

                                                                                                                                        0
                                                                                                                                        Вот вам такой краевой пример: если таймер симуляции будет настроен на 100000 рассчетов/сек и будет игнорировать факт забора, то при любом ФПС игра будет выглядеть плавно.
                                                                                                                                          0
                                                                                                                                          Нет. Будет как в статье. Физика есть на любой момент данных, кадры выдаются на экран равномерно. Но картинка на них дергается, так как значение физики будет браться на неправильный момент.
                                                                                                                                            0
                                                                                                                                            Ладно, давайте проще. У нас вообще нет дисплея, есть некоторый таймер, который каждые 10 тиков опрашивает модель. Будет ли он наблюдать рывки, если модель ничего про этот таймер не знает, а просто производит внутреннюю симуляцию?
                                                                                                                                              0
                                                                                                                                              Если модель имеет внутренний таймер не кратный 10 тикам то будут рывки. Например модель считается быстрее каждые 9 тиков, то каждый 9 кадр будет в два раза быстрее.
                                                                                                                                              Поэтому важно синхронизировать два таймера. Но корректных данных о тиках внешнего таймера нет.
                                                                                                                                                0
                                                                                                                                                Если модель имеет внутренний таймер не кратный 10 тикам то будут рывки.

                                                                                                                                                Значит достаточно, чтобы внутренний таймер был кратен, или достаточно быстрым, чтобы рыки не были заметны. Например если будет рывок в 10 микросекунд то вряд ли он будет заметен.
                                                                                                                                                  0
                                                                                                                                                  Как раз на экране рывок в 10 мс виден по статье. Генерация физики 500-1000 раз в секунду лишь поуменьшит лаги но не устранит полностью. Слишком затратно по CPU.

                                                                                                                                                  А вот синхронизация на равный тики действительно решает проблему. Но только корректно померить тики видеокарты на данный момент нельзя
                                                                                                                                                    0
                                                                                                                                                    Как раз на экране рывок в 10 мс виден по статье.

                                                                                                                                                    10мкс в 1000 раз меньше

                                                                                                                                                    А вот синхронизация на равный тики действительно решает проблему. Но только корректно померить тики видеокарты на данный момент нельзя

                                                                                                                                                    Ну понятное дело, что идеальное решение иметь обратную связь. Но когда это будет…
                                                                                                                                                      0
                                                                                                                                                      Ну понятное дело, что идеальное решение иметь обратную связь. Но когда это будет…

                                                                                                                                                      Но раньше это идеальное решение практически всегда и работало. Просто сейчас видеокарта стала настолько сложной, что ситуация стала возникать чаще чем раньше
                                                                                                                                            0
                                                                                                                                            На шейдертое симуляция вообще высчитывается из всего диапазона float iGlobalTime, это эквивалентно 1/FLOAT_MIN рассчетов/сек, без учета ошибок округления. Это не помогает, проблема вот в чем:
                                                                                                                                            image

                                                                                                                                            Вот какую проблему решал и решил гугл.
                                                                                                                                              0
                                                                                                                                              Наскольок я понимаю, тут проблема в неконтролируемом GC. Что ж, чтобы это работало, никаких GC быть не должно и кадры должны выводиться с одной частотой (если они готовы).
                                                                                                                                                0
                                                                                                                                                с какой, если в играх возможно ситуация, когда рендеринг кадров будет происходить дольше, чем частота их обновления на мониторе?
                                                                                                                                                  0
                                                                                                                                                  Рендреринг кадров происходит быстрее, чем частота обновления на мониторе. Но видеокарта сообщает, что кадр отрисовался не сразу, а только после выполнения внутренних процедур.
                                                                                                                                                  Со стороны кажется, что рендер не поспевает и происходит адаптация под проседания fps.
                                                                                                                                                    0
                                                                                                                                                    Нет, главная проблема, что рендеринг кадров может быть дольше частоты обновления из-за разного уровня железа и загруженностей ОС у игроков.
                                                                                                                                                    Поэтому система обратной связи должна быть. И вот уже из-за косячности данной обратной связи оказывается, что система адаптации начинает косячить в тех местах, где проблем не было.
                                                                                                                                                    Поэтому решения ренедерить с определенной частотой — бессмысленны, ибо у части пользователей тормоза будут не мифические, а реальные и играть они тогда вообще не смогут.
                                                                                                                                                      0
                                                                                                                                                      Но видеокарта сообщает, что кадр отрисовался не сразу, а только после выполнения внутренних процедур.

                                                                                                                                                      Не надо спрашивать у видеокарты ничего — тогда и не существенно, что она сообщает.

                                                                                                                                                    0
                                                                                                                                                    > никаких GC быть не должно и кадры должны выводиться с одной частотой (если они готовы).

                                                                                                                                                    Проблема в том, что по факту это не так. Это может быть не GC, а что угодно, просто наблюдаемый факт, что драйвер чем-то занимается после реального обновления. У меня это проявляется и на Linux и на Windows. Драйверам никто не запрещает это делать, по документации все четко, ничего не нарушается. Да и от GC никуда не деться, если не на swap его выполнять (когда как раз кадр завершили и логично почистить), на идущий следом glClear()? В общем кривота это все, знать реальное время отображения нужно, без этого никуда.
                                                                                                                      +4
                                                                                                                      Вы не поняли. Речь тут не идет о физике вообще. Как бы вы её ни считали, даже если она у вас непрерывная каким-то образом, а не дискретными кадрами — проблема предсказания положения объекта на момент отображения остается. Просто потому что на начало рендеринга кадра надо знать положение объекта на момент когда этот самый кадр будет в итоге отображен игроку. Иначе движение не будет плавным. И это время плохо предсказуемо. И даже для уже отрендеренных в прошлом кадров её сложно (невозможно?) узнать, про что и статья.
                                                                                                                        0
                                                                                                                        Вам нужно делать 1 фотографию в секунду, а получается примерно 0,9. И что теперь по такому таймеру делать? Пропускать каждый второй кадр?
                                                                                                                          0
                                                                                                                          Тоже думал об этом и кажется понял (спасибо kosmos89). Идея в том что чтобы вывести видео на экран нам в симуляции нужна последовательность моментов времени которым будут соответствовать показанные кадры. Эта последовательность не равномерна и зависит от GPU, т.к. время отрисовки каждого кадра варьируется. Так вот померять эту последовательность правильно — сложно. А при ошибочном замере имеем наблюдаемую проблему когда время симуляции рассинхронизируется с реальным временем показа картинки. И неважно считается ли при этом физика только в нужные для отображения моменты времени или равномерно по таймеру, так что две трети кадров остается невостребованной (последнее кстати явно выглядит как способ угробить производительность).
                                                                                                                          0
                                                                                                                          А разве мы не можем просто…

                                                                                                                          … считать физику независимо от отрисовки? То есть один поток считает физику (время вычислений на CPU отлично измеряется), а другой периодически у него забирает последнее актуальное состояние. Тогда эффекта опережения не может быть (во всяком случае по причине неверно рассчитанного dt).
                                                                                                                            –1
                                                                                                                            Да собственно так и делается в современных играх. Потоки необязательно разные, но тики физики идут от стабильного таймера, и обычно с чатотой выше, чем кадры. В статье боль разработчиков, оставшихся душёй в тех самых 90-ых.
                                                                                                                              +1
                                                                                                                              Проблема описанная в статье не в расчете физики. Проблема в том в какие моменты времени забираются рассчитанные данные. Эти моменты привязаны к тому что показывается на экране, т.е. зависят от GPU, и не являются равномерно распределенными. А дальше стоит потоку читающему состояние мира чуть-чуть притормозить с забором данных для кадра #50, как считающийся в параллельном потоке мир обновится и поток уже прочитает данные которые были бы валидны для кадра 50,1.
                                                                                                                                0
                                                                                                                                Отклонения такого порядка глазом не должны быть видны.
                                                                                                                                  0
                                                                                                                                  Ну вот как показывает практика, при задержке порядка 60 мс — отлично видны.
                                                                                                                                  На винде это как раз примерное время preemption для потоков foreground-процесса
                                                                                                                                    +1
                                                                                                                                    Не совсем понимаю. 60мс — это что? Отставание рендеринга от состояния мира? Каким образом это замерялось? Или это просто проседание времени кадра? Тогда конечно будет видно, это очень много. И в любом случае 60мс — это не доли кадра, это три с половиной кадра для 60FPS.
                                                                                                                                      0
                                                                                                                                      Ошибся, не 60 мс а 6 мс. Это отставание момента реального чтения мира от момента когда чтение мира было запрошено GPU. Замерялось путем замера момента времени обращения рендерера за состоянием мира и сопоставления этого времени с временем при равномерной частоте смены кадров
                                                                                                                                        +1
                                                                                                                                        Не совсем уловил объяснение замера. Речь о вызовах в каком-то движке или вызовах OpenGL/DirectX? Каких именно? Вы ведь сами обновляете состояние сцены на GPU, а не он запрашивает состояние.
                                                                                                                                          0
                                                                                                                                          Ну, у Вас всегда есть какая-то логика которая решает когда пора начинать рисовать следующий кадр. Эта логика как-то синхронизируется с GPU потому что грубо говоря нет смысла начинать рисовать следующий кадр когда еще предыдущий не дорисовался. Это я и называю «запрос от GPU». Этой логике требуется определять состояние игрового мира для этого нового кадра. В идеале — на момент времени когда для этого кадра произойдет buffer swap, в реальности — скорее всего на момент времени swap buffer минус какой-то фиксированный лаг чтобы этот момент уже находился в прошлом а не в будущем. Но по факту запрос состояния мира идет на момент времени когда выполнение кода на CPU реально дошло до этой логики и она реально запросила данные у физического движка. Поскольку время от момента swap buffer до момента запроса состояния мира может непредсказуемым образом меняться то получаем описываемый в статье рассинхрон
                                                                                                                            +2
                                                                                                                            Статья и перевод просто шикарны! Спасибо! Сам когда очень давно начинал в GL долго не мог понять, почему замер скорости участка кода рисования вместе в glFinish + SwapBuffers дает ~16ms вместо положенных ~60-100 микросекунд, если измерять без этих команд. Но, как оказывается, и эти 60-100 микросекунд — обман на самом деле.
                                                                                                                            Кстати у меня иногда проскакивает «статтер» и на правильном плавном видео, благо только 1 на весь ролик.
                                                                                                                              0

                                                                                                                              Интересненько (про видео), напомнило старые времена, когда принудительно выставляли на мониторе (CRT) частоту кадров, кратную частоте кадров видео. А позже ещё какие-то трюки были для просмотра 50Гц видео на 60Гц мониторе, я уж подзабыл.

                                                                                                                                0
                                                                                                                                > Кстати у меня иногда проскакивает «статтер» и на правильном плавном видео, благо только 1 на весь ролик.

                                                                                                                                У меня 2 раза, второй на обратном пути, почти незаметный.
                                                                                                                                –1
                                                                                                                                Чую, производители железа будут против внедрения массовых программных оптимизаций :) Ведь это закон Мура может нарушить) Как тогда им продавать все более и более дорогие видеокарты?)
                                                                                                                                  0
                                                                                                                                  И все таки основная проблема тут в том, что время рендера кадра скачает. Анимации можно отвязать и показывать с фиксированным FPS, но так как кадр «плавает», то все это будет выглядеть дергано. А вот то, что время кадра так сильно скачает — я думаю это таки проблема оптимизации. Например постоянные реаллокации GPU ресурсов, объектов GAPI и тому подобное.
                                                                                                                                  Пример: каждый кадр вызывают glBufferData с разными размерами, вместо того, чтобы один раз вызвать glBufferData с запасом, и обновлять его через glBufferSubData.
                                                                                                                                    0
                                                                                                                                    Время рендера кадра не скачет. В статье же сказано, что если принудительно считать временем рендера 16.6 то все хорошо. Кадры будут успевать отрисовываться. Но если пытаться узнать за какое время отрисовался кадр, то иногда получают завышенное число в 24 мс. Из которых на рендеринг кадра ушло меньше 16 мс, а остальное время драйвер занимался внутриними вещами уже после отрисовки и показа кадра.
                                                                                                                                      0
                                                                                                                                      Ну допустим. А зачем нам в этом случае вообще считать время кадра? Почему бы в этом случае не отвязать рендер от игровой логики? Сделать игровую логику и забор инпута с фиксированным фреймрейтом, а рендерить в остальное свободное время?
                                                                                                                                        0
                                                                                                                                        Рендер и так отвязан от игровой логики. Как указано в статье забор инпута с фиксированным фреймрейтом действительно решает проблему. Но это работает только пока вы успеваете рендерить кадр без просадки fps.
                                                                                                                                        Если же надо рендерить при плавающем fps, то проблема никуда не девается. Физика игры берёться не на текущий момент, а на текущее время+ время рендеринга кадра. И если gpu говорит что не успевает отрисовать за 16, и успела только за 24 то игра пытается компенсировать просадку fps нарисовав кадр в более далеком будущем. Но в реальности просадки fps нет и кадр опережает реальный мир.
                                                                                                                                          0
                                                                                                                                          Но это работает только пока вы успеваете рендерить кадр без просадки fps.

                                                                                                                                          Всмысле? Ну вот просел FPS до 20, а мы все равно забираем инпут и обновляем физику с частотой 60 раз в секунду. Почему это не работает то?

                                                                                                                                          Физика игры берёться не на текущий момент, а на текущее время+ время рендеринга кадра.

                                                                                                                                          Зачем физику брать на момент + время рендеринга кадра? Почему просто не брать физику от фиксированного времени без всякого плюс время рендеринга кадра?
                                                                                                                                            0
                                                                                                                                            Ну посчитали физику 60 в секунду, а потом пытаемся отобразить кадр попадающий не точно в то момент, а на 8 мс позднее. Ровно посередине тика расчета физики, для него какое значение брать. А если соседние с ним кадры попадёт ровно в тик? Будет два подряд одинаковых кадра?

                                                                                                                                            Если не учитывать время рендеринга то картинка будет запаздывать, по ощущениям будет похоже что игра тормозит.

                                                                                                                                              0
                                                                                                                                              Физику принято считать чаще, чем частота кадров. Соответственно, два кадра одинаковыми не будут, а небольшую задержку (доли кадра) с состоянием мира вы на глаз не увидите.
                                                                                                                                                0
                                                                                                                                                Как раз небольшую задержку в полкадра на видео в статье мы и видим. Там кадр ошибся по времени в 8 мс.
                                                                                                                                                0
                                                                                                                                                Если не учитывать время рендеринга то картинка будет запаздывать, по ощущениям будет похоже что игра тормозит.
                                                                                                                                                Уверяю вас, вы не почувствуете, что игра тормозит даже если изображение будет запаздывать на 16мс. Но ок, допустим мы знаем, что мы хотим получать 60FPS, и что у пользователя практически всегда будут стабильные 60FPS. В этом случае мы можем делать константную поправку на 16мс вперед. А если вдруг у пользователя FPS просядет до 30 в какой-то момент, то ок, он получит маленькую задержку в 16мс, что не смертельно.

                                                                                                                                                В статье описывается как раз другой случай, когда при стабильных 60FPS время, когда кадр реально появляется на экране сильно ёрзает, и за счет этого мы собственно и видим рывки.
                                                                                                                                                  0
                                                                                                                                                  В статье описано как раз наоборот, кадр стабильно появляется на 60fps.
                                                                                                                                                  Он появляется вовремя и стабильно, но игра думает что иногда FPS проседает(хотя это и не правда) и пытается адаптироваться под проседание fps путём измения константы времени кадра. Что в свою очередь приводит к опережению по времени

                                                                                                                                                  Когда же они ставили постоянные 60 FPS они по факту и делали это поправку константой в 16 мс и лаги переставали наблюдаться.
                                                                                                                                                    0
                                                                                                                                                    Они пытались делать поправку от времени предыдущего кадра. Предыдущий кадр обрабатывался 24мс, они делают поправку на 24мс. В результате мало того, что кадр был нарисован с задержкой, так и для следующего кадра поправка будет в 8 секунд вперед.
                                                                                                                                                      0
                                                                                                                                                      Нарисован то кадр будет во время, но вот поправка действительно неверная. А что делать то если единственный источник откуда поправку модно взять( GPU) врет и выдаёт иногда не верные значения.
                                                                                                                                      0
                                                                                                                                      Странно, но на рабочем компе со слабой видюхой почему-то все представленные видео местами плавно, а местами тормозят.
                                                                                                                                        0
                                                                                                                                        Выскажу бредовую идею — GPU надо встраивать в монитор, а не в компьютер ?)
                                                                                                                                          +2
                                                                                                                                          Идея бредовая — пропускная способность PCIE около 240 гбит, а HDMI — около 18 гбит.
                                                                                                                                            +2
                                                                                                                                            К тому же совершенно не решает указанную выше проблему, а может даже ухудшит положение. Проблема не в том, что кадр идёт долго до монитора, а в том что драйвер отвечает что кадр отрисован с плавающей задержкой. При этом задержки на самом деле нет, это он просто занимался внутренними вещами.
                                                                                                                                          –4

                                                                                                                                          У бетезды в движках при падении ФПС замедляется игровой таймер, и ничего, никаких проблем это не вызывает.

                                                                                                                                            –5
                                                                                                                                            Это можно решить выделением отрисовки и обновления мира в разные потоки. Когда мы начинаем рендерить сцену то берём наиболее актуальный снапшот игрового мира.
                                                                                                                                            Обновление же игрового мира при этом живёт своей жизнью.
                                                                                                                                            Это одна из первых вещей с которыми сталкиваешься при разработке игры без привлечения готовых движков.
                                                                                                                                              0
                                                                                                                                              Nani?
                                                                                                                                              –1
                                                                                                                                              У меня стала наблюдаться проблема со схожим графиком «пульсаций» но в другом временном масштабе: каждые секунд пять (приблизительно) нормальное fps прерывается полным замиранием изображения на полсекунды.
                                                                                                                                              Вот кто бы объяснил, в чём дело, и как с этим бороться. Я уж и vsync переключал, и другие опции крутил…

                                                                                                                                              Началось это после перехода на Win7 с XP, причём на неновых уже играх — Чистое небо, Borderlands, Bioshock. На том же железе (где-то тех же лет сборки, уже тогда он был далеко не топ, но для подобных игр хватало — даже Crysis на средних настройках шёл).

                                                                                                                                              Поставил на отдельный диск обратно XP — там всё нормально, только памяти не всем играм хватает (некоторые моды на сталкер довольно требовательны). Не, ну я понимаю, что сама операционка сколько-то ресурсов отжирает, и видимо, семерка таки побольше чем XP. Хотя встречал утверждения, что наоборот — семерка оптимизированнее и всё такое, а десятка так вообще…
                                                                                                                                                0
                                                                                                                                                Меня вот другое интересует, как эта вдруг проблема всплывает в 2018? А что, простите, раньше это было неизвестно? Никто не замечал?
                                                                                                                                                  +2
                                                                                                                                                  Проблема настолько тонкая, что даже в комментариях к этой статье предлагают решения, хотя в статье объяснено, почему решения не существует.