Я пытаюсь лучше понять требования к синхронизации при работе с 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.