Как преобразовать существующую текстуру OpenGL в металлическую текстуру

Я работаю над разработкой некоторых плагинов для FxPlug для Motion и FCP X. В конечном счете, я бы хотел, чтобы они рендерились в металле, так как Apple осуждает OpenGL.

В настоящее время я использую CoreImage, и, хотя я смог использовать функциональность CoreImage для обработки металла вне SDK FxPlug, FxPlug предоставляет мне только рамку в качестве текстуры OpenGL. Я попытался просто передать это в фильтр CoreImage, но в итоге получаю эту ошибку:

Cannot render image (with an input GL texture) using a metal-DG context.

После небольшого исследования я обнаружил, что я могу предположительно использовать CVPixelBuffers для совместного использования текстур между ними, но после некоторой попытки написать код, использующий этот метод, я пришел к выводу, что это было задумано как способ НАПИСАТЬ (например, создать с нуля) в общий буфер, но не конвертировать между ними. Хотя это может быть неправильно, я не могу найти способ заставить существующую текстуру GL существовать в CVPixelBuffer.

TL; DR: я нашел способы получить результирующую текстуру Metal или OpenGL из CVPixelBuffer, но я не могу найти способ создать CVPixelBuffer из существующей текстуры OpenGL. Мое сердце не настроено на этот метод, так как моя конечная цель - просто конвертировать из OpenGL в Metal, а затем обратно в OpenGL (в идеале, эффективным способом).

Кто-нибудь еще нашел способ работать с FxPlug с Metal? Есть ли хороший способ конвертировать текстуру OpenGL в Metal/CVPixelBuffer?

1 ответ

Решение

Я написал FxPlug, который использует текстуры OpenGL и текстуры металла. То, что вы ищете, это IOSurface, Это текстуры, которые можно использовать с Metal или OpenGL, хотя они имеют некоторые ограничения. Таким образом, если у вас уже есть текстура Metal или OpenGL, вы должны скопировать ее в IOSurface использовать его с другой системой.

Чтобы создать IOSurface Вы можете использовать CVPixelBuffers (включая kCVPixelBufferIOSurfacePropertiesKey) или вы можете напрямую создать его, используя IOSurface класс, определенный в <IOSurface/IOSurfaceObjC.h>,

Как только у вас есть IOSurfaceВы можете скопировать свою текстуру OpenGL в нее, получив текстуру OpenGL из IOSurface с помощью CGLTexImageIOSurface2D() (определено в <OpenGL/CGLIOSurface.h>). Затем вы берете эту текстуру и используете ее в качестве вспомогательной текстуры для FBO. Вы можете, например, нарисовать текстурированный квад в нем, используя ввод FxTexture в качестве текстуры. Будь уверен в звонке glFlush() когда сделано!

Далее возьмите IOSurface и создать MTLTexture от этого через -[MTLDevice newTextureWithDescriptor:ioSurface:plane:] (описано здесь). Вы хотите создать выход IOSurface привлечь, а также создать MTLTexture от него. Сделайте ваш металлический рендеринг на выходе MTLTexture, Далее возьмите вывод IOSurface и создать из него текстуру OpenGL через CGLTexImageIOSurface2D(), Теперь скопируйте эту текстуру OpenGL в выходной FxTexture, используя ее как основу FBO с текстурной поддержкой или любым другим методом, который вы предпочитаете.

Как вы можете видеть, недостатком этого является то, что для каждого рендера требуется 2 копии - 1 вход в IOSurface и 1 выход IOSurface в выходную текстуру приложение дает вам. Другим недостатком является то, что это, вероятно, спорный вопрос, поскольку Apple публично объявила о прекращении поддержки OpenGL и, вероятно, уже работает над решением на основе Metal. Это может быть дополнительная работа, чтобы сделать все это самостоятельно. (Хотя плюс в том, что вы можете использовать этот же код в других хост-приложениях, которые поддерживают только OpenGL.)

Другие вопросы по тегам