macOS iOS Metal 开发爬坑总结

文档列表见:Rust 移动端跨平台复杂图形渲染项目开发系列总结(目录)

【持续更新】

已知问题:

  1. iOS 12新增接口renderTargetArrayLength。此接口默认值应该为0,表示禁用层渲染。若不小心设置为1,则出现Metal参数验证断言失败,信息如下:

    -[MTLRenderPassDescriptorInternal validate:width:height:]:1972: failed assertion `renderTargetArrayLength > 0 specified, but Layered Rendering is not supported on this device.'

    The default value is 0, indicating layered rendering is not enabled.

    developer.apple.com/documentati…

  2. Capture GPU Frame在iMac AMD显卡和MacBook Intel显卡的不同表现。 相同Metal代码在:

    • iMac 5k Later 2015、macOS 10.14、Xcode 9.4.1,没法Capture GPU Frame,推测是AMD显卡驱动写的不够好,2017年同一台iMac用macOS 10.13也遇到此问题。
    • MacBook Mid 2015、macOS 10.13.5、Xcode 9.4.1,可以Capture GPU Frame。不过,如果只通过MTLHeap创建Texture并上传纹理数据,由于不是完整绘制流程,没有Scope停止信号导致Capture GPU Frame确实捕获到Command Buffer,也就无法进入在线调试界面。
  3. 非Draw Call调用无法进入在线调试界面,非Draw Call是指MTLCommandBuffer的commit()waitUntilCompleted()。 由前面实践得出此结论。二次验证是RenderPass只配置ClearColor,渲染到纹理。

    let submit = {
        let mut cmd_buffer = command_pool.acquire_command_buffer(false);
    
        cmd_buffer.set_viewports(0, &[viewport.clone()]);
        {
            let mut encoder = cmd_buffer.begin_render_pass_inline(
                &render_pass,
                &framebuffer,
                viewport.rect,
                &[command::ClearValue::Color(command::ClearColor::Float([0.0, 1.0, 0.5, 1.0]))],
            );
        };
    
        cmd_buffer.finish()
    };
    let submission = Submission::new()
        .wait_on(&[(&frame_semaphore, PipelineStage::BOTTOM_OF_PIPE)])
        .submit(Some(submit));
    queue_group.queues[0].submit(submission, Some(&mut frame_fence));
    queue_group.queues[0].wait_idle(); // 等待队列任务执行完成
    复制代码
  4. 验证Capture GPU Frame的Scope信号,即是Capture GPU Frame的结束信号,否则Xcode会一直收集MTLCommandBuffer却不进入Replay Frame界面,即前面说的调试界面。根据我的开发经验,结束信号可在代码中主动调用MTLCaptureScope实现,也会由MTLCommandBuffer::presentDrawable:MTLCommandBuffer::waitUntilCompleted + MTLRenderCommandEncoder::drawPrimitives系列函数触发,但是,由于TBDR机制与Metal驱动的性能调优原因,原则上只有发出MTLCommandBuffer::presentDrawable:指令后,MTLCommandQueue才会执行已入队的MTLCommandBuffer,这是TBDR中的DR工作机制。

你可能感兴趣的:(macOS iOS Metal 开发爬坑总结)