У меня есть металлический шейдер, который обрабатывает видеокадр iPad Pro для создания (не отображаемого) изображения RGBA32Float в цветном приложении. Затем эту текстуру пропускают через фильтр MPSImageIntegral, закодированный в тот же командный буфер, что и шейдер, что приводит к выходному изображению того же размера и формата. В обработчике завершения буфера команд я считал последний пиксель в отфильтрованном изображении (содержащем сумму всех пикселей во входном изображении), используя этот код:
let src = malloc(16) // 4 Floats per pixel * 4 bytes/Float
let region = MTLRegionMake2D(imageWidth - 1, imageHeight - 1, 1, 1) // last pixel in image
outputImage!.getBytes(src!, bytesPerRow: imageWidth * 16, from: region, mipmapLevel: 0)
let sum = src!.bindMemory(to: Float.self, capacity: 4)
NSLog("sum = \(sum[0]), \(sum[1]), \(sum[2]), \(sum[3])")
, который работает правильно, пока текстуры удержание входного и отфильтрованного изображений имеют одинаковый размер с дисплеем IPad, 2048 x 2732, хотя с такими большими изображениями это происходит медленно.
Чтобы ускорить его, я заставил шейдер генерировать только размер ¼ (512 x 683) Вместо этого используйте изображение RGBA32Float и используйте тот же размер и формат для вывода фильтра. Но в этом случае сумма, которую я вычитал, всегда равна нулю.
За счет захвата кадров графического процессора в отладчике я вижу, что графики зависимостей выглядят одинаково в обоих случаях (за исключением уменьшенных размеров текстуры в последнем случае) и что шейдер и фильтр работают в обоих случаях, как и ожидалось, в зависимости от внешнего вида входных и отфильтрованных текстур, как показано в отладчике. Так почему же я больше не могу успешно считывать эти отфильтрованные данные, когда единственным изменением было уменьшение размера входного и выходного изображений фильтра?
Некоторые вещи, которые я уже сделал попытался, но безрезультатно:
- Использование изображений 512 x 512 (и другого размера), чтобы избежать возможных артефактов заполнения в изображениях 512 x 683.
- Глядя на другие пиксели, около середины выходного изображения, которые также содержат ненулевые данные в соответствии со снимками графического процессора, но которые читаются как 0 при использовании меньших изображений.
- Использование MTLBlitCommandEncoder в том же буфере команд для копирования выходного пикселя в MTLBuffer вместо или в дополнение к использованию getBytes. (Это было предложено в ответе на этот вопрос MacOS , который не имеет прямого отношения к iOS.)