howt to convert metal texture to opengles texture with a fast speed?

I had a case , which output a metal texture(MTLTexture), and then I need import it into a opengles pipeline using opengles texture.

So I need to convert it , any methods for this using GPU?

(Maybe using CPU,we could convert to cpu memory (like pixelbuffer) and load it again with opengles )

Replies

The way to do this is via CoreVideo PixelBuffers. You can create a CVPixelBuffer and then create both a Metal texture and an OpenGL texture that share the same underlying storage.


The broad steps would be:


// setup

Create a CVPixelBufferPool

Create a CVMetalTextureCache

Create a CVOpenGLESTextureCache

(the Cache objects cache Metal and OpenGL textures for buffers within the pool, so they don't end up thrashing)


// per frame

Get a CVPixelBuffer from the pool

Get a Metal texture from the cache, issue rendering, commit, and waitUntilScheduled

Get a OpenGL texture from the cache, issue rendering commands that read from that texture.


If you are building something like a media pipeline, you may be cycling through a set of CVPixelBuffers in the pool. If you only ever need one texture and you can reuse it frame after frame, then you can move the 'get textures from the cache' to the Setup phase.

Hi @Frogblast

Thanks for your reply.

My case as follows,

I get a metal textrue cache from a video output delegate function, and i push this texture into GPU and use metal compute pipeline to process.

At last I need to push last MTLTexture into a opengles library.

So my flow should be as follow:

Getting a metal textrue from video frame(and new a cvpixelbuffer from smaplebuffer) one by one , at the same time, I need create a opengles texture from the same cvpixelBuffer. And then,I could use kernel to process this metal texture and should render it into a colorattachment and commit,and using waitUntilScheduled to wait cpu and gpu freshing into pixelbuffer memory.

so now I get the opengles texture from render color attachment.


is it right above?

Hello -- I followed your instructions and was able to get Metal and OpenGL to use the same textures. But the colors are swapped. Metal only allows BGRA_unorm as a pixel format, whereas OpenGL seems to only accept RGBA. How to get around that?

Metal does have MTLPixelFormatRGBA8Unorm.


Have you tried calling CVPixelBufferCreate with kCVPixelFormatType_32RGBA and calling CVMetalTextureCacheCreateTextureFromImage with MTLPixelFormatRGBA8Unorm?

The problem is that I am rendering to the Metal texture, and the MTKView's colorPixelFormat cannot be RGBA8Unorm. It can only be BGRAUnorm. Metal only works with BGRA, and OpenGL only works with RGBA. Doh!


Currently I am getting around the problem by just reversing the R and B in the fragment shader when I render my OpenGL texture.

You're correct that RGBA8Unorm is not an allowable format for a drawable texture. OpenGL does support BGRA (but not for a drawable on iOS at least).


You really need the texture to be displayed in both an OpenGL view and a Metal view? Usually only one API is used for display so the API that isn't displaying rehder does not need to render to a drawable but only an offscreen texture (which give more flexibility in your choice of pixel formats)

I see -- yes, I guess I do not need Metal to render to a drawable, it can render to an offscreen. I will try that, thanks!