Как вы синхронизируете 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>
для деталей.)