Простой подход, который должен работать в большинстве случаев, состоит в том, чтобы вычислить время, в которое вы хотите нарисовать кадр, и использовать метод present(_:atTime:)
для MTLCommandBuffer
вместо метода present(_:)
.
Чтобы обеспечить больший контроль, это помогает понять, что делают и не делают методы present...
буфера команд.Они не кодируют любую команду в буфер.Как документировано, они в основном просто добавляют запланированный обработчик, который вызывает present
на отрисовке.
Если вы осторожны с этим, вы можете организовать представление отрисовки так, чтобы это не сильнозадействуйте буфер команд.
Но имеет ли смысл буфер команд, использующий запланированный обработчик 1015 *?Разве он не должен использовать обработчик complete ?В конце концов, вы хотите отобразить завершенный рендеринг, верно?
Что ж, прорисовки хороши при представлении.Метод present
отображается не сразу.Нарисованные треки, которые запланированные команды могут визуализировать или записать в свою текстуру.Когда вызывается present
, это позволяет рисовать себя на экране как можно быстрее после выполнения всех таких команд .(Обратите внимание, что это не означает, что сам буфер команд завершен. Могут быть дополнительные команды, которые не включают текстуру рисованного объекта, которая еще не завершена.)
Это обеспечивает как проблемы, так и возможности для синхронизациипрезентация нескольких рисунков.Проблема в том, что, хотя вы можете контролировать, когда вы вызываете present
на каждом рисованном объекте, это не обязательно синхронизирует их фактическое отображение, потому что каждый будет отображаться как можно скорее после вызова present
, и все команды, включающие его текстуру,завершена, и эта последняя часть может происходить в разное время для разных элементов рисования.
Один из возможных подходов к решению этой проблемы - добавить представленный обработчик в основной чертеж.Обработчик будет вызывать present
на других 3 чертежах.После того, как все командные буферы запланированы, вызовите present
на главном чертеже.Вы можете использовать группу диспетчеризации, чтобы определить, когда запланированы все буферы команд.Введите группу один раз для каждого буфера команд и добавьте запланированный обработчик для каждого, кто покидает группу.Затем установите блок уведомлений в группе, в которой присутствует мастер.Этот метод, вероятно, не достигнет идеальной синхронизации, потому что существует задержка между тем, когда мастер-объект рисования фактически представлен, и когда вызывается представленный обработчик, и затем задержкой при представлении других элементов рисования.
Другой возможный подход - установитьpresentsWithTransaction
свойство всех ваших CAMetalLayer
s к истине.Затем, когда пришло время представить, вызовите waitUntilScheduled
в каждом буфере команд, а затем present
в каждой отрисовке.(Не используйте метод present...
буфера команд.) Это будет гарантировать, что все прорисовываемые объекты будут представлены во время одной и той же транзакции Core Animation, то есть синхронизированы.