Я делаю обработку видео в реальном времени на iOS со скоростью 120 кадров в секунду и хочу сначала предварительно обработать изображение на графическом процессоре (сокращение, преобразование цвета и т.д., которые недостаточно быстры для процессора) и более поздний постпроцессный фрейм на CPU с использованием OpenCV.
Какой самый быстрый способ обмена каналами камеры между GPU и CPU с помощью Metal?
Другими словами, труба будет выглядеть так:
CMSampleBufferRef -> MTLTexture or MTLBuffer -> OpenCV Mat
Я конвертирую CMSampleBufferRef → MTLTexture следующим образом
CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
// textureRGBA
{
    size_t width = CVPixelBufferGetWidth(pixelBuffer);
    size_t height = CVPixelBufferGetHeight(pixelBuffer);
    MTLPixelFormat pixelFormat = MTLPixelFormatBGRA8Unorm;
    CVMetalTextureRef texture = NULL;
    CVReturn status = CVMetalTextureCacheCreateTextureFromImage(NULL, _textureCache, pixelBuffer, NULL, pixelFormat, width, height, 0, &texture);
    if(status == kCVReturnSuccess) {
        textureBGRA = CVMetalTextureGetTexture(texture);
        CFRelease(texture);
    }
}
После того, как мой металлический шейдер завершен, я конвертирую MTLTexture в OpenCV
cv::Mat image;
...
CGSize imageSize = CGSizeMake(drawable.texture.width, drawable.texture.height);
int imageByteCount = int(imageSize.width * imageSize.height * 4);
int mbytesPerRow = 4 * int(imageSize.width);
MTLRegion region = MTLRegionMake2D(0, 0, int(imageSize.width), int(imageSize.height));
CGSize resSize = CGSizeMake(drawable.texture.width, drawable.texture.height);
[drawable.texture getBytes:image.data bytesPerRow:mbytesPerRow  fromRegion:region mipmapLevel:0];
Некоторые наблюдения:
1) К сожалению, MTLTexture.getBytes кажется дорогим (копирование данных с GPU на CPU?) и занимает около 5 мс на моем iphone 5S, что слишком много при обработке со скоростью ~ 100 кадров в секунду
2) Я заметил, что некоторые люди используют MTLBuffer вместо MTLTexture со следующим методом:   metalDevice.newBufferWithLength(byteCount, options: .StorageModeShared)
(см. Производительность записи памяти - Общая память процессора GPU)
Однако CMSampleBufferRef и сопутствующий CVPixelBufferRef управляется CoreVideo - это предположение.
