I'm using a CARenderer
to render another CALayer
tree into a CAMetalLayer
, which I hope to use as the mask
of yet another layer. For testing purposes, I've tried adding the CAMetalLayer
as a normal sublayer instead of a mask.
The layer
object below is not visible after adding it to a superlayer that is definitely visible. I've confirmed the frame
of the layer is not a problem. Here's how I'm making the CAMetalLayer
and its CARenderer
.
CAMetalLayer *layer = [CAMetalLayer layer];
layer.frame = bounds;
layer.device = MTLCreateSystemDefaultDevice();
//layer.opaque = NO;
//layer.framebufferOnly = NO;
id<CAMetalDrawable> drawable = layer.nextDrawable;
_lastDrawable = drawable;
_renderer = [CARenderer rendererWithMTLTexture:drawable.texture options:nil];
_renderer.layer = self.superview.layer;
_renderer.bounds = bounds;
👇 By creating a CIImage
and inspecting it with the debugger, I've confirmed the CARenderer
is updating the Metal texture.
CIImage *img = [CIImage imageWithMTLTexture:_lastDrawable.texture options:nil];
But when I set the superlayer
of the CAMetalLayer
, it's nowhere to be seen.
[self.layer addSublayer:layer];
Here's how I'm using the CARenderer
:
[_renderer beginFrameAtTime:CACurrentMediaTime() timeStamp:NULL];
[_renderer addUpdateRect:bounds];
[_renderer render];
[_renderer endFrame];
That last snippet runs frequently.
I've added a backgroundColor
and now the layer
is visible, but its texture is not being rendered inside it.
layer.backgroundColor = NSColor.yellowColor.CGColor;
I would recommend just setting the original layer as a mask rather than trying to render it to a texture first; you’re sort of duplicating the work that CA would be doing anyway.
If you really need control over when the mask layer tree gets rendered—and again you should definitely try the standard method first—the right way to do this would be to create an IOSurface-backed MTLTexture rather than using a CAMetalLayer’s drawable, draw into the texture with your CARenderer, set the IOSurface as the contents of a regular CALayer, and use that layer as the mask.