How to crop the shape of an image out of a caShape layer,

Assuming your "P image (or any image)" has transparent (alpha) areas such as this (the P is surrounded by transparency):

enter image description here

so it would look like this in a UIImageView:

enter image description here

You can create an "inverted transparency" image:

    guard let pImage = UIImage(named: "pImage") else {
        print("Could not load mask image!")
        return
    }
    
    // size of view you want to mask
    let sz: CGSize = CGSize(width: 200, height: 200)
    // rect to draw the mask image (where we want the "P")
    let maskRect:CGRect = CGRect(x: 50, y: 100, width: 100, height: 80)
    
    let renderer = UIGraphicsImageRenderer(size: sz)
    let iMaskImage = renderer.image { ctx in
        // fill with black (any color other than clear will do)
        ctx.cgContext.setFillColor(UIColor.black.cgColor)
        ctx.fill(CGRect(origin: .zero, size: sz))
        // draw the image in maskRect with .xor blendMode
        //  this will make all non-transparent pixels in the image transparent
        pImage.draw(in: maskRect, blendMode: .xor, alpha: 1.0)
    }

At that point, iMaskImage will be this (the white "P" shape is not white... it's transparent):

enter image description here

You can then use that image as a mask on any other view.

Here's an example MaskedTriangleView -- it uses a CAShapeLayer for the triangle, and then uses the "P" image as a layer mask:

class MaskedTriangleView: UIView {
    
    let shapeLayer = CAShapeLayer()
    var maskImage: UIImage?

    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }
    func commonInit() {
        layer.addSublayer(shapeLayer)
        shapeLayer.fillColor = UIColor.systemYellow.cgColor
        shapeLayer.strokeColor = UIColor.blue.cgColor
        shapeLayer.lineWidth = 1
    }
    override func layoutSubviews() {
        super.layoutSubviews()
        
        // create a triangle shape path
        let bez: UIBezierPath = UIBezierPath()
        bez.move(to: CGPoint(x: bounds.minX, y: bounds.maxY))
        bez.addLine(to: CGPoint(x: bounds.midX, y: bounds.minY))
        bez.addLine(to: CGPoint(x: bounds.maxX, y: bounds.maxY))
        bez.close()
        shapeLayer.path = bez.cgPath
        
        if let img = maskImage {
            // let's make our mask image
            //  50% of the height of self
            let h: CGFloat = bounds.height * 0.5
            //  40% from the Top (leaving 10% space at the bottom)
            let y: CGFloat = bounds.height * 0.4
            //  keep it proportionally sized
            let ratio: CGFloat = h / img.size.height
            //  width is proportional to height
            let w: CGFloat = img.size.width * ratio
            //  center horizontally
            let x: CGFloat = (bounds.width - w) * 0.5
            
            // rect to draw the mask image
            let maskRect:CGRect = CGRect(x: x, y: y, width: w, height: h)
            
            let renderer: UIGraphicsImageRenderer = UIGraphicsImageRenderer(size: bounds.size)
            let iMaskImage: UIImage = renderer.image { ctx in
                // fill with black (any color other than clear will do)
                ctx.cgContext.setFillColor(UIColor.black.cgColor)
                ctx.fill(CGRect(origin: .zero, size: bounds.size))
                // draw the image in maskRect with .xor blendMode
                //  this will make all non-transparent pixels in the image transparent
                img.draw(in: maskRect, blendMode: .xor, alpha: 1.0)
            }
            // create a layer
            let maskLayer: CALayer = CALayer()
            // set the new image as its contents
            maskLayer.contents = iMaskImage.cgImage
            // same frame as self
            maskLayer.frame = bounds
            // use it as the mask for the shape layer
            shapeLayer.mask = maskLayer
        }
    }
    
}

and it will look like this (the top image is overlaid on an image view, the bottom image is added as a subview of the main view, with the green background showing through):

enter image description here

Here's the example controller:

class ImageMaskingVC: UIViewController {
    
    var bkgImageView: UIImageView!
    var triangleView1: MaskedTriangleView!
    var triangleView2: MaskedTriangleView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.backgroundColor = .systemGreen
        
        // make sure we can load the images
        guard let bkimg = UIImage(named: "samplePic") else {
            print("Could not load background image!")
            return
        }
        
        guard let pImage = UIImage(named: "pImage") else {
            print("Could not load mask image!")
            return
        }
        
        // create the image view and set its image
        bkgImageView = UIImageView()
        bkgImageView.image = bkimg
        
        // create a MaskedTriangleView and set its maskImage
        triangleView1 = MaskedTriangleView()
        triangleView1.maskImage = pImage
        
        // create another MaskedTriangleView and set its maskImage
        triangleView2 = MaskedTriangleView()
        triangleView2.maskImage = pImage
        
        // add the views
        [bkgImageView, triangleView1, triangleView2].forEach {
            if let v = $0 {
                v.translatesAutoresizingMaskIntoConstraints = false
                view.addSubview(v)
            }
        }

        let g = view.safeAreaLayoutGuide
        
        NSLayoutConstraint.activate([
            
            // constrain background image view
            //  Top / Leading / Trailing at 20-pts
            bkgImageView.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
            bkgImageView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
            bkgImageView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
            
            // height proportional to background image size
            bkgImageView.heightAnchor.constraint(equalTo: bkgImageView.widthAnchor, multiplier: bkimg.size.height / bkimg.size.width),

            // constrain first MaskedTriangleView exactly on top of the background image view
            triangleView1.topAnchor.constraint(equalTo: bkgImageView.topAnchor, constant: 20.0),
            triangleView1.leadingAnchor.constraint(equalTo: bkgImageView.leadingAnchor, constant: 20.0),
            triangleView1.trailingAnchor.constraint(equalTo: bkgImageView.trailingAnchor, constant: -20.0),
            triangleView1.bottomAnchor.constraint(equalTo: bkgImageView.bottomAnchor, constant: -20.0),

            // constrain the second MaskedTriangleView below the background image view
            //  with same width and height as the first MaskedTriangleView
            triangleView2.topAnchor.constraint(equalTo: bkgImageView.bottomAnchor, constant: 20.0),
            triangleView2.widthAnchor.constraint(equalTo: triangleView1.widthAnchor, constant: 0.0),
            triangleView2.heightAnchor.constraint(equalTo: triangleView1.heightAnchor, constant: 0.0),
            
            // centered horizontally
            triangleView2.centerXAnchor.constraint(equalTo: triangleView1.centerXAnchor, constant: 0.0),

        ])
        
    }
    
}