Как вы синхронизируете MTLTexture и IOSurface между процессами?

Какие 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 предположить, что блокировка только для доступа к процессору.)

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

1 ответ

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

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

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

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

Другие вопросы по тегам