Как вы синхронизируете MTLTexture и IOSurface между процессами? - PullRequest
0 голосов
/ 03 февраля 2019

Какие API мне нужно использовать и какие меры предосторожности я должен предпринять при записи в IOSurface в процессе XPC, который также используется в качестве резервного хранилища для MTLTexture в основном приложении?

В моей службе XPC у меня есть следующее:

IOSurface *surface = ...;
CIRenderDestination *renderDestination = [... initWithIOSurface:surface];

// Send the IOSurface to the client using an NSXPCConnection.
// In the service, periodically write to the IOSurface.

В моей заявке у меня есть следующее:

IOSurface *surface = // ... fetch IOSurface from NSXPConnection.
id<MTLTexture> texture = [device newTextureWithDescriptor:... iosurface:surface];

// The texture is used in a fragment shader (Read-only)

У меня есть MTKView, который работает, это нормальный цикл обновления.Я хочу, чтобы моя служба XPC могла периодически выполнять запись в IOSurface с использованием Core Image, а затем отображать новое содержимое Metal на стороне приложения.

Какая синхронизация необходима для обеспечения правильной работы?Стратегия двойной или тройной буферизации - одна, но она мне не подходит, потому что у меня может не хватить памяти, чтобы выделить в 2 или 3 раза больше поверхностей. (В приведенном выше примере для ясности используется одна поверхность, но на самом деле у меня могут быть десятки поверхностей, на которые я рисую. Каждая поверхность представляет плитку изображения. Изображение может быть настолько большим, насколько позволяет JPG / TIFF / и т. Д..)

WWDC 2010-442 говорит о IOSurface и кратко упоминает, что все это «просто работает», но это в контексте OpenGL и не упоминает Core Image или Metal.

Изначально я предполагал, что Core Image и / или Metal будут вызывать IOSurfaceLock() и IOSurfaceUnlock() для защиты доступа на чтение / запись, но, похоже, это не так. (А комментарии в заголовочном файле для IOSurfaceRef.h предполагают, что блокировка только для доступа к процессору.)

Могу ли я просто позволить CIRenderDestination Core Image писать по желанию вIOSurface пока я читаю из соответствующего MTLTexture в цикле обновления моего приложения?Если это так, то как это возможно, если, как утверждает видео WWDC, все текстуры, связанные с IOSurface, совместно используют одну и ту же видеопамять?Конечно, я бы немного порвал содержимое поверхности, если бы чтение и запись происходили во время одного и того же прохода.

1 Ответ

0 голосов
/ 03 февраля 2019

Все, что вам нужно сделать, это убедиться, что рисование CoreImage завершено в XPC, прежде чем IOSurface будет использоваться для рисования в приложении.Если бы вы использовали OpenGL или Metal с обеих сторон, вы бы либо позвонили glFlush(), либо [-MTLRenderCommandEncoder waitUntilScheduled].Я бы предположил, что что-то в CoreImage делает один из этих вызовов.

Я могу сказать, что, скорее всего, это будет очевидно, если этого не произойдет, потому что вы получите разрывы или изображения, наполовину новые и наполовину старые, есливещи не правильно синхронизированы.Я видел, как это происходит при использовании IOSurface s в XPC.

Одна вещь, которую вы можете сделать, это установить несколько символических точек останова на -waitUntilScheduled и -waitUntilCompleted и посмотреть, вызывает ли CI их в вашем XPC (при условии, что документация явно не говорит вам).В Metal есть и другие примитивы синхронизации, но я с ними не очень знаком.Они также могут быть полезны.(Насколько я понимаю, CI теперь весь металл под капотом.)

Кроме того, у объекта IOSurface есть методы -incrementUseCount, -decrementUseCount и -localUseCount.Возможно, стоит проверить их, чтобы убедиться, что CI устанавливает их соответствующим образом.(Подробнее см. <IOSurface/IOSurfaceObjC.h>.)

...