Vulkan MacOS 下调试 shader

672 阅读2分钟

Apple 的 Metal 已经来到了3.0版本,所以到倒闭他也不可能去支持 Vulkan。 但是 Moltenvk 这个项目能让开发者在 MacOS 下写跨平台图形应用,它把你 shader 生成的 SPIR-V 转换成 metal shader 文件,然后在 MacOS 下以 Metal Framework 的方式运行,所以调试 Metal 的方法同样适用于 Moltenvk

起因

Vulkan Spec 的 文档的时候,对GLSLcomponent 属性的用法感到好奇,于是简单的画了个三角形,但是一直没有图像输出,于是想调试一下 GPU 数据。 MacOS 并没有 RenderDoc 之类的东西,不过 Xcode 自带 GPU 调试,具体启用方法看 Apple - Metal debug shaders

过程

我的 Demo 是 Cmake 写的,所以直接生成 Xcode 项目,启用 Metal Debug 的方法如下:

  1. 在项目 TARGETS 选择你的项目

  2. 选中 Build Phases

  3. 添加 Metal.framework lib

之后你在底部控制台 就可以看到一个 Metal 的小图标 用来抓帧数据了。

Screen Shot 2022-06-30 at 10.49.07.png

现在讲讲 component 的用法,其实是对同一份数据,进行一个偏移量的访问,对于不同类型的偏移位,官方文档有详细的表格。

// 这是我想上传的顶点数据
glm::vec4 vertData[] = {

// we use components keywords.

    {0.1f, 0.2f, 0.3f, 0.4f},

    {0.5f, 0.6f, 0.7f, 0.8f},

    {0.9f, 1.0f, 1.1f, 1.2f},

};

// shader 部分代码

layout(location = 0, component = ?) in vec3 position;

gl_Position = vec4(position, 1.0);

这是 Xcode 捕获到的帧数据,下图是 component = 0 的情况,发现虽然上传的是vec4,但是还是按照 vec3 使用, m_18 属性的值 和 我们上传的意义对应,注意到 gl_Position 的 y 分量是相反的。

Screen Shot 2022-06-30 at 10.55.42.png

看看 component = 1 的情况,发现数据有偏移了,访问了后面 三个分量。

Screen Shot 2022-06-30 at 11.01.54.png

那么为什么 gl_Position 的 y 分量是负数? 其实看一看 SPIR-V 翻译生成的 Metal 代码就知道了。

#include <metal_stdlib>
#include <simd/simd.h>

using namespace metal;
struct main0_out

{
    float3 m_28 [[user(locn0)]];
    float4 gl_Position [[position]];
};


struct main0_in
{
    float4 m_location_0 [[attribute(0)]];
};


vertex main0_out main0(main0_in in [[stage_in]])
{
    main0_out out = {};
    float3 _18 = {};
    _18 = in.m_location_0.yzw;
    out.gl_Position = float4(_18, 1.0);
    out.m_28 = float3(_18.x, _18.y, _18.z);
    out.gl_Position.y = -(out.gl_Position.y); // Invert Y-axis for Metal
    return out;

}

发现生成的位置 y 做了个反转, 至于为什么反转,因为 Metal Spec 规定的 y 正方向 和 Vulkan 的 坐标系可能有所不同,可自行查阅。

总结

流水账一般的文章,但是确实 蛮有用的。让我感触最大的 跨平台框架 的实现真的太不容易了。