MTKView issue.

Today i have little problem and I can't understand what's happened. I'm trying to implement realtime applying CIFIlter(s) to image from video stream using MTKView without delegate. I have this error:

Take image and send to processing code:



extension CameraCamptureOperator: AVCaptureVideoDataOutputSampleBufferDelegate {
    func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
        DispatchQueue.main.async {
            connection.videoOrientation = AVCaptureVideoOrientation(rawValue: UIApplication.shared.statusBarOrientation.rawValue) ?? .portrait
        }
       
        guard let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { return }
        DispatchQueue.main.async {[weak self] in
            self?.delegate?.campturedNewImage(CIImage(cvImageBuffer: pixelBuffer))
        }
       
    }
}

In didSet image, I calling render():


  private func renderingInProcess() {
       
        guard let image = imageToDraw,
            let targetTexture = mtkView.currentDrawable?.texture else { return }
       
        let commandBuffer = GraphicApi.commandQueue?.makeCommandBuffer()
        let render = mtkView.currentRenderPassDescriptor
        render?.colorAttachments[0].clearColor = .init(red: 244.0/255.0, green: 241.0/255.0, blue: 238.0/255.0, alpha: 1.0)
        let renderEncoder = commandBuffer?.makeRenderCommandEncoder(descriptor: render!)
        renderEncoder?.endEncoding()
        let scaleX = mtkView.drawableSize.width / image.extent.width
        let scaleY = mtkView.drawableSize.height / image.extent.height
        let scale = min(scaleX, scaleY)
       
        let scaledImage = image.transformed(by: CGAffineTransform(scaleX: scale, y: scale))
       
       
        var bounds = CGRect(origin: .zero, size: mtkView.drawableSize)
        if scale == scaleX {
            let space = (mtkView.drawableSize.height - scaledImage.extent.height) / 2
            let origin = CGPoint(x: 0, y: -space)
            bounds.origin = origin
        } else {
            let space = (mtkView.drawableSize.width - scaledImage.extent.width) / 2
            let origin = CGPoint(x: -space, y: 0)
            bounds.origin = origin
        }
       
        GraphicApi.context.render(scaledImage,
                         to: targetTexture,
                         commandBuffer: commandBuffer,
                         bounds: bounds,
                         colorSpace: GraphicApi.colorSpace)
       
       
        commandBuffer!.present(mtkView.currentDrawable!)
       
        commandBuffer!.commit()
    }


[CAMetalLayerDrawable present] should not be called after already presenting this drawable. Get a nextDrawable instead.


[Common] _BSMachError: port 600b; (os/kern) invalid capability (0x14) "Unable to insert COPY_SEND"


Execution of the command buffer was aborted due to an error during execution. Discarded (victim of GPU error/recovery) (IOAF code 5)


2018-11-29 22:07:58.446854+0200 AVCIProject[1244:223735] [Common] _BSMachError: port 5597; (os/kern) invalid capability (0x14) "Unable to insert COPY_SEND"

Answered by Pan Biny in 676001022
The following is my the modified code, no error tips 【CAMetalLayerDrawable present] should not be called after already presenting this drawable. Get a nextDrawable instead.】, hope it helps you.

code:

Code Block
-(void)startRender() {
dispatch_block_t renderBlock = ^ { @autoreleasepool {
......
......
id<MTLTexture> drawingTexture =  metalView.currentDrawable.texture;
......
passDescriptor.colorAttachments[0].texture = drawingTexture;
......
......
[renderEncoder popDebugGroup];
[renderEncoder endEncoding];
[commandBuffer presentDrawable:[(CAMetalLayer*)metalView.layer nextDrawable] ];
[commandBuffer commit];
}};
 ([NSThread isMainThread])?renderBlock():dispatch_async(dispatch_get_main_queue(), renderBlock);
}

It may be in other background threads before rendering, when GPU start render, used dispatch_async(get_main), make sure render work in main thread.


Accepted Answer
The following is my the modified code, no error tips 【CAMetalLayerDrawable present] should not be called after already presenting this drawable. Get a nextDrawable instead.】, hope it helps you.

code:

Code Block
-(void)startRender() {
dispatch_block_t renderBlock = ^ { @autoreleasepool {
......
......
id<MTLTexture> drawingTexture =  metalView.currentDrawable.texture;
......
passDescriptor.colorAttachments[0].texture = drawingTexture;
......
......
[renderEncoder popDebugGroup];
[renderEncoder endEncoding];
[commandBuffer presentDrawable:[(CAMetalLayer*)metalView.layer nextDrawable] ];
[commandBuffer commit];
}};
 ([NSThread isMainThread])?renderBlock():dispatch_async(dispatch_get_main_queue(), renderBlock);
}

It may be in other background threads before rendering, when GPU start render, used dispatch_async(get_main), make sure render work in main thread.


MTKView issue.
 
 
Q