Как улучшить рендеринг MTKView при использовании MPSImageScale и MTLBlitCommandEncoder - PullRequest
0 голосов
/ 08 ноября 2018

TL; DR: из моего MTKView метода моего делегата drawInMTKView: часть моего прохода рендеринга включает в себя добавление MPSImageBilinearScale быстродействующего шейдера и ноль или более MTLBlitCommandEncoder запросов на generateMipmapsForTexture. Это разумно сделать изнутри drawInMTKView:, что происходит в главном потоке? Блокирует ли кто-либо из них основной поток во время работы или они только кодируются, а затем выполняются позже и полностью на GPU?

Более длинная версия:

Я играю с металлом в контексте приложения обработки изображений. Я использую Core Image для загрузки изображения и применения фильтров. Выходное изображение отображается в виде 2D-плоскости на виде металла с одной текстурой. Это работает, но для повышения производительности я хотел поэкспериментировать со способностью Core Image визуализировать меньшие плитки одновременно. Каждая плитка отображается в своем собственном IOSurface.

На каждом проходе рендеринга я проверяю, есть ли плитки, которые были недавно отрисованы. Для каждой визуализированной плитки (которая теперь IOSurface) я создаю текстуру металла из CVMetalTextureCache, которая опирается на поверхность.

Я думаю, используйте масштабирование MPS, чтобы скопировать текстуру плитки в "основную" текстуру. Если плитка была скопирована, тогда я запускаю команду blit для создания мипмапов на основной текстуре.

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

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

Если я уменьшу размер моей «основной» текстуры, то генерация mipmap будет выполняться быстрее, так как только грязные текстуры являются обновлениями, но, как представляется, есть нижние границы того, насколько маленьким я должен сделать основную текстуру, потому что, если я делаю ее слишком маленький, тогда мне нужно передать большое количество текстур фрагментному шейдеру. (И похоже, что этот предел может быть 128?)

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

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

...