Metal Render Loop оптимизация
Я ищу руководство о том, как правильно реализовать цикл рендеринга Metal. Мой цикл рендеринга получает поток видеокадров из AVPlayer
,
Вот моя текущая реализация:
-
CVDisplayLink
запрашиваетAVPlayerItemVideoOutput
игрока в 60 Гц. Если есть новый кадр, этоCVPixelBufferRef
захватывается / сохраняется * как свойствоMTKView
к которому это будет оказано. (На этом этапе ранее захваченный видеокадр освобождается). - мой
MTKView
настроен сisPaused
а такжеenableSetNeedsDisplay
вNO
, Другими словами, внутренний таймерMTKView
поручено периодически вызывать егоdrawRect
метод. - В
drawRect
Я сначала преобразовать вновь прибывших *CVPixelBuffer
кMTLTexture
, а затем происходит куча этапов рендеринга. - Наконец я звоню
presentDrawable
в концеdrawRect
метод.
* Примечание: мьютексный доступ к CVPixelBufferRef
контролируется спариванием dispatch_semaphore_wait
а также dispatch_semaphore_signal
,
Это правильный способ делать вещи? Это кажется довольно производительным, хотя некоторые кадры иногда пропускаются. С точки зрения времени, профилирование Xcode Metal говорит мне, что MTLCommandBuffer
обычно занимает менее 3 мс для запуска.
Сказав это, я вижу некоторые альтернативные возможности:
- угробить
CVDisplayLink
реализация и захватить кадры внутриdrawRect
- обратный процесс рендеринга; отобразить ранее захваченный кадр и визуализированный
MTLTexture
первый вdrawRect
метод, а затемcommit
этот металлический буфер команд и вызовpresentDrawable
в кратчайшие сроки. После этого снимите следующий видеокадр и проведите его через все этапы рендеринга до следующегоdrawRect
позвонить (сделать это раньшеdrawRect
выходит?).
Еще одна проблема: у меня сложилось впечатление, что оба CVDisplayLink
а также drawRect
методы не были запущены в главном потоке с этой конфигурацией. Меня беспокоит тот факт, что всякий раз, когда я отказываюсь от одного из меню приложения, возникает значительная задержка в доставке видеокадров - это симптоматично, когда основной поток выполняет обновления пользовательского интерфейса и блокируется. Такое же поведение наблюдается, когда на экране NSCollectionView
перезагружается и его содержимое анимируется на экране. Это приводит меня к мысли, что мое предположение неверно. Как это может MTKView
сделать рендеринг циклов, чтобы избежать этих проблем? Хотите знать, если все открытие / конфиг AVPlayer
должен быть отключен от основного потока.
ОБНОВЛЕНИЕ № 1
Я исправил проблемы с заиканием " Другая проблема ", которые возникали при использовании NSMenu
Предметы. Это было мое решение:
- Настройте каждый
MTKView
сisPaused=YES
а такжеenableSetNeedsDisplay=NO
, Это означает, что явноеdraw
вызовы необходимы для представления, чтобы представить его содержание. - Изнутри
CVDisplayLink
перезвонить, выдатьdraw
позвонить вMTKView
наdispatch_global_queue
, таким образом:
__block MTKView *aView = ....;
dispatch_queue_t aQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(aQueue, ^{ [aView draw]; });