Search code examples
swiftmacoscocoametalmetalkit

Copy Metal frame buffer texture for reading


I'm trying to take a screenshot of a MetalKit view (MTKView) like in the answer Take a snapshot of current screen with Metal in swift but it requires that the MTKView set framebufferOnly to false which disables some optimizations according to Apple.

Is there a way to copy the MTKView texture (e.g. view.currentDrawable.texture) so that I can read the pixels? I don't need to take screenshots often so it would be a shame to disable the optimization for the entire lifecycle of the program running.

I tried using MTLTexture.newTextureViewWithPixelFormat and blit buffers but I still get the same exception about the frame buffer only being true.


Solution

  • When a screenshot is requested, you could toggle framebufferOnly, do one rendering pass, and then toggle it back.

    Alternatively, you can do one rendering pass targeting a texture of your own specification, blit that to the drawable's texture (so as not to visually drop a frame), and then save the contents of your own texture.