MPSImageIntegral возвращает все нули, когда изображения меньше - PullRequest
0 голосов
/ 10 января 2020

У меня есть металлический шейдер, который обрабатывает видеокадр 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 и используйте тот же размер и формат для вывода фильтра. Но в этом случае сумма, которую я вычитал, всегда равна нулю.

За счет захвата кадров графического процессора в отладчике я вижу, что графики зависимостей выглядят одинаково в обоих случаях (за исключением уменьшенных размеров текстуры в последнем случае) и что шейдер и фильтр работают в обоих случаях, как и ожидалось, в зависимости от внешнего вида входных и отфильтрованных текстур, как показано в отладчике. Так почему же я больше не могу успешно считывать эти отфильтрованные данные, когда единственным изменением было уменьшение размера входного и выходного изображений фильтра?

Некоторые вещи, которые я уже сделал попытался, но безрезультатно:

  1. Использование изображений 512 x 512 (и другого размера), чтобы избежать возможных артефактов заполнения в изображениях 512 x 683.
  2. Глядя на другие пиксели, около середины выходного изображения, которые также содержат ненулевые данные в соответствии со снимками графического процессора, но которые читаются как 0 при использовании меньших изображений.
  3. Использование MTLBlitCommandEncoder в том же буфере команд для копирования выходного пикселя в MTLBuffer вместо или в дополнение к использованию getBytes. (Это было предложено в ответе на этот вопрос MacOS , который не имеет прямого отношения к iOS.)

1 Ответ

0 голосов
/ 10 января 2020

Я обнаружил, что если я изменю storeAction дескриптора прохода рендеринга для цветового вложения шейдера, который получает исходное входное изображение RGBA32Float с .dontCare на .store, то код работает для изображений 512 x 683, а также 2048 x 2732 те.

Почему это работало без этого для больших изображений, я до сих пор не знаю.

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

...