Как синхронизировать Metal Performance Shader с MTLBlitCommandEncoder? - PullRequest
0 голосов
/ 24 августа 2018

Я пытаюсь лучше понять требования к синхронизации при работе с Metal Performance Shaders и MTLBlitCommandEncoder.

У меня есть MTLCommandBuffer, который настроен следующим образом:

  • Используйте MTLBlitCommandEncoder, чтобы скопировать область текстуры A в текстуру B. Текстура A больше, чем текстура B. Я извлекаю «плитку» из текстуры A и копирую ее в текстуру B.

  • Используйте металлический шейдер MPSImageBilinearScale с текстурой B в качестве исходной текстуры и третьей текстурой, C, в качестве места назначения.Этот металлический высокопроизводительный шейдер будет масштабировать и потенциально переводить содержимое текстуры B в текстуру C.

Как убедиться, что blit-кодировщик полностью завершает копирование данных из текстуры A в текстуру B до того, какметаллический шейдер производительности начинает пытаться масштабировать текстуру B?Должен ли я беспокоиться об этом, или последовательный характер буфера команд уже позаботился об этом?

В Metal есть концепция ограждений, использующих MTLFence для синхронизации доступа к ресурсам, но я не вижу, чтобы металлический шейдер производительности ждал на заборе.(Принимая во внимание, что waitForFence: присутствует на кодировщиках.)

Если я не могу использовать заборы и мне нужно синхронизировать, рекомендуется просто поставить в очередь blit-энкодер, затем вызвать waitUntilCompleted наБуфер команд перед включением шейдера и вызовом waitUntilCompleted во второй раз?Пример:

id<MTLCommandBuffer> commandBuffer;

// Enqueue blit encoder to copy Texture A -> Texture B
id<MTLBlitCommandEncoder> blitEncoder = [commandBuffer blitCommandEncoder];
[blitEncoder copyFromTexture:...];
[blitEncoder endEncoding];

// Wait for blit encoder to complete.
[commandBuffer commit];
[commandBuffer waitUntilCompleted];

// Scale Texture B -> Texture C
MPSImageBilinearScale *imageScaleShader = [[MPSImageBilinearScale alloc] initWithDevice:...];  
[imageScaleShader encodeToCommandBuffer:commandBuffer...];

// Wait for scaling shader to complete.
[commandBuffer commit];
[commandBuffer waitUntilCompleted];

Причина, по которой я думаю, что мне нужно сделать промежуточное копирование в текстуру B, заключается в том, что MPSImageBilinearScale, кажется, масштабирует всю исходную текстуру.clipOffset полезен для вывода, но он не применяется к реальному масштабированию или преобразованию.Таким образом, плитка должна быть извлечена из текстуры A в текстуру B того же размера, что и сама плитка.Тогда масштабирование и преобразование будут «иметь смысл». Не обращайте внимания на эту сноску, потому что я забыл некоторые основные математические принципы и с тех пор выяснил, как заставить свойства преобразования масштабного преобразования работать с clipRect.

1 Ответ

0 голосов
/ 24 августа 2018

Металл позаботится об этом за вас. Драйвер и графический процессор выполняют команды в буфере команд, как если бы они были последовательными. («Как будто» позволяет запускать вещи параллельно или не по порядку для эффективности, но только в том случае, если результат будет таким же, как при последовательном выполнении.)

Проблемы синхронизации возникают, когда и CPU, и GPU работают с одними и теми же объектами. Также с представлением текстур на экране. (Вы не должны рендерить текстуру, которая представлена ​​на экране.)

Есть раздел в Руководстве по программированию Metal , который касается доступа для чтения и записи к ресурсам шейдерами, что не совсем то же самое, но должно вас успокоить:

Барьеры памяти

Между командными кодерами

Все записи ресурсов, выполненные в заданном кодере команд, являются видимыми в следующей команде кодировщик. Это верно как для визуализации, так и для вычислений. кодировщики команд.

в кодировщике команд визуализации

Для буферов атомарные записи видны для последующих атомарных чтений в нескольких потоках.

Для текстур метод textureBarrier обеспечивает запись выполненные в данном вызове отрисовки видны для последующих чтений в следующий розыгрыш.

в кодировщике вычислительных команд

Все записи ресурсов, выполненные в данной функции ядра, видны в следующей функции ядра.

...