2

I have a drawing app using Metal, that works well on newer iPhones and iPads. However, on older devices like the 6th and 7th generation iPad, the screen shows up as blank transparent view.

I checked the code that handles the drawing, and it seems like everything is being drawn properly onto a output texture.

Debug Metal drawing with XCode: Debug with XCode

When I click on "drawPrimitives:TriangleStripp": Debug drawPrimitives:TriangleStrip

The output texture (in Attachments): The output texture (in Attachments)

The contents in the output texture is what I want to display on the screen, but it do not work on old devices, to display the texture on the screen, I use this code:

if let drawable = currentDrawable {
    commandBuffer?.present(drawable)
}

It only works on new devices, then I tried to use this code without success:

commandBuffer?.addCompletedHandler({ [weak self] commandBuffer in
    DispatchQueue.main.async {
        self?.currentDrawable?.present()
    }
})

Here is the complete code of the drawRect function:

open override func draw(_ rect: CGRect) {
super.draw(rect)

let texture = self.renderer.texture

// 1. Render existing strokes
let renderPassDescriptor = MTLRenderPassDescriptor()
let attachment = renderPassDescriptor.colorAttachments[0]
attachment?.clearColor = clearColor
attachment?.texture = currentDrawable?.texture
attachment?.loadAction = .clear
attachment?.storeAction = .store

let commandBuffer = commandQueue?.makeCommandBuffer()

let commandEncoder = commandBuffer?.makeRenderCommandEncoder(descriptor: renderPassDescriptor)

commandEncoder?.setRenderPipelineState(pipelineState)

commandEncoder?.setVertexBuffer(render_target_vertex, offset: 0, index: 0)
commandEncoder?.setVertexBuffer(render_target_uniform, offset: 0, index: 1)
commandEncoder?.setFragmentTexture(texture, index: 0)


commandEncoder?.drawPrimitives(type: .triangleStrip, vertexStart: 0, vertexCount: 4)

commandEncoder?.endEncoding()
if let drawable = currentDrawable {
    commandBuffer?.present(drawable)
}

// Completion handler
commandBuffer?.addCompletedHandler({ [weak self] commandBuffer in
    // This is how I know the contents has been rendered to texture:
    
    DispatchQueue.main.async {
        self?.currentDrawable?.present()
    }
})

commandBuffer?.commit()
}

I checked the frame of the metalView, there is no problem and I able to see it in the view hiearachy.

I've been struggling with this bug all day. Could you guys give me some suggestions? Thanks a lot

Brew Master
  • 457
  • 3
  • 13
  • for older devices try adding ```mtkView.sampleCount = 1``` ```mtkView.isOpaque = true``` ```mtkView.framebufferOnly = true```. try using them separately and in combinations. – udi Mar 03 '23 at 05:08
  • I tried separately and in combinations but non of them worked. Setting isOpaque to true make the MKTView completely black. The other 2 options do not change anything – Brew Master Mar 03 '23 at 16:02
  • Just added more images for debugging. Any other suggestions? – Brew Master Mar 06 '23 at 02:43

0 Answers0