文档列表见:
根据kvark指导,Xcode创建External Build System项目可通过Capture GPU Frame查看的examples绘制过程,略出乎意料,我没想过可以这么干(浪),虽然2015年我用External Build System单步调试过FFmpeg源码,但是我不知道Xcode也支持这种形式的Capture GPU Frame,可以说很无知且没有探索精神了。
虽然gfx-hal有完美的日志输出,但是,作为刚接触gfx项目和Rust的初学者,有时我想确认程序流程是否符合预期(我一直在忙其他事,很少看Rust语法,这是个人失误),即便Rust写日志输出比C++方便很多,不过图形项目开发过程中还是帧回放定位问题的效率最高 。但是,折腾一番,我在3台mac(MacBook Pro + iMac)上一执行就崩溃。在他本地测试也崩溃。我觉得可能是工程配置出错了,原因是,终端直接运行gfx/examples/quad等可执行文件是正常的。
客观地说,隔了一段时间没用Xcode,我不熟悉它的配置了,然后考虑并验证了下列几个替代方案:
- Rust暴露C接口接入macOS项目。给gfx/examples填写FFI接口,让C/C++调用Rust实现的功能。在绘制过程中正常使用Capture GPU Frame。
- 利用Metal MTLCommandBuffer addCompletedHandler接口添加执行完成的日志。缺点是,只能验证MTLCommandBuffer确实被GPU执行完,没法查看渲染结果。用Compute Shader做数值计算场合用这个方案倒是可以接受。
- 类似上一方案,不输出日志,改为读取MTLCommandBuffer目标纹理的像素值,通过CIImage生成图像,通过Xcode插件进行查看。缺点,在线调试Shader没Capture GPU Frame方便。
然而,我还是没法放弃Capture GPU Frame by External Build System方案,因为它配置和二次开发成本最低,最合适我们当前的团队状态。花了好长时间,在Josh的帮助下,终于解决了。
问题现象: examples/三个项目以External Build System项目形式在Xcode中运行后崩溃,提示信息:
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 20, kind: Other, message: "Not a directory" }', libcore/result.rs:1009:5note: Run with `RUST_BACKTRACE=1` for a backtrace.ERROR 2018-11-30T07:12:36Z: gfx_backend_metal::command: Command buffer not released properly!thread 'main' panicked at 'assertion failed: !self.active', src/backend/metal/src/command.rs:55:9复制代码
结论: External Build Tool Configuration的Directory配置项只用于build过程,对于Rust项目,src/
和target/
是两个不同的目录,examples/
那些项目要求的编译和执行路径是examples/
,根本原因是,examples代码用fs::read_to_string()
通过相对路径加载glsl源码文件!此时相对路径前面的完整路径就隐式限制为examples/
。然而,Xcode的播放按钮功能是Build and then run the current scheme,Build阶段配置正常了,问题出在Run阶段,需要传递正确的路径,示例如下图所示。
正常的Capture GPU Frame截图。
下面复盘当时的尝试过程,流下了无知的泪水。
- 同一个电脑(10.14 + Xcode 9.4.1 (9F2000))上依次尝试examples/三个demo项目。运行失败,下面简写成失败。
- 换两台电脑(10.13.5 + Xcode 9.4.1 (9F2000)、10.13.5 + Xcode 10 )尝试上一步骤 ——> 失败。
- 重置代码库,获取最新代码,重新用Xcode运行 ——> 失败。
- 去掉Xcode
Main Thread Checker
,重新用Xcode运行 ——> 失败。 - 修改Rust编译工具链,依次用nightly、stable,清掉编译缓存,重新编译,重新用Xcode运行 ——> 失败。
- 升级Rust编译工具链,重复上一步骤 ——> 失败。
- 反复修改External Build Tool Configuration的三个配置项,确认它们的值都正确 ——> 失败。
- 修改Xcode工程位置,重复前面所有步骤 ——> 失败。
- 修改当前Scheme/Run/Debug/Info的所有配置项,重复前面所有步骤 ——> 失败。
- 搜索更多Xcode运行Rust项目资料并逐一修改,重复前面所有步骤 ——> 失败。
- 和别人讨论解决方案 ——> 失败,开始接近问题本质原因。感谢齿轮哥。
- 在Terminal切换到
target/debug/
执行quad
——> 失败,报错和Xcode几乎一致。 - 查看源码,找到
fs::read_to_string()
——> 问题差不多定位。 - 修改源码加上完整文件路径 ——> Xcode运行不崩溃,但是Capture GPU Frame不可用,问题完全定位。
- 换成MacBook Pro重复上一步骤 ——> 正常。推断:iMac (Retina 5K, 27-inch, Late 2015)在10.14下驱动有问题。
- 最终Josh给了更好的解决方案(见结论部分),无需修改源码。
- 齿轮哥建议使用
concat!(env!())
补全gfx-hal/examples的shader源码路径,我实现后提了PR,老外不同意合并。