naga icon indicating copy to clipboard operation
naga copied to clipboard

Name clash when converting to Metal

Open almarklein opened this issue 4 years ago • 0 comments

Consider the following WGSL shader:

struct VertexInput {
    [[builtin(vertex_index)]] index : u32;
};
struct VertexOutput {
    [[location(0)]] color : vec4<f32>;
    [[builtin(position)]] pos: vec4<f32>;
};

[[stage(vertex)]]
fn vs_main(in: VertexInput) -> VertexOutput {
    var positions = array<vec2<f32>, 3>(vec2<f32>(0.0, -0.5), vec2<f32>(0.5, 0.5), vec2<f32>(-0.5, 0.7));
    let index = i32(in.index);
    let p: vec2<f32> = positions[index];

    var out: VertexOutput;
    out.pos = vec4<f32>(p, 0.0, 1.0);
    out.color = vec4<f32>(p, 0.5, 1.0);
    return out;
}

[[stage(fragment)]]
fn fs_main(in: VertexOutput) -> [[location(0)]] vec4<f32> {
    return in.color;
}

This validates successfully and runs fine on Vulkan and DX12. But when running on Metal, this produces an error:

thread '' panicked at 'Internal { stage: VERTEX, error: "Metal: Compilation failed: \n\nprogram_source:xx:y: error: redefinition of 'index' with a different type: 'int' vs 'metal::uint' (aka 'unsigned int')\n int index = static_cast(in.index);

When I use Naga from the command-line to convert to a metal shader I get:

// language: metal1.1
#include <metal_stdlib>
#include <simd/simd.h>

struct VertexInput {
    metal::uint index;
};
struct VertexOutput {
    metal::float4 color;
    metal::float4 pos;
};
struct type3 {
    metal::float2 inner[3];
};

struct vs_mainInput {
};
struct vs_mainOutput {
    metal::float4 color [[user(loc0), center_perspective]];
    metal::float4 pos [[position]];
};
vertex vs_mainOutput vs_main(
  metal::uint index [[vertex_id]]   // <------
) {
    const VertexInput in = { index };
    type3 positions;
    VertexOutput out;
    for(int _i=0; _i<3; ++_i) positions.inner[_i] = type3 {metal::float2(0.0, -0.5), metal::float2(0.5, 0.5), metal::float2(-0.5, 0.699999988079071)}.inner[_i];
    int index = static_cast<int>(in.index);   // <-----
    metal::float2 p = positions.inner[index];
    out.pos = metal::float4(p, 0.0, 1.0);
    out.color = metal::float4(p, 0.5, 1.0);
    VertexOutput _e25 = out;
    const auto _tmp = _e25;
    return vs_mainOutput { _tmp.color, _tmp.pos };
}


struct fs_mainInput {
    metal::float4 color [[user(loc0), center_perspective]];
};
struct fs_mainOutput {
    metal::float4 member1 [[color(0)]];
};
fragment fs_mainOutput fs_main(
  fs_mainInput varyings1 [[stage_in]]
, metal::float4 pos [[position]]
) {
    const VertexOutput in1 = { varyings1.color, pos };
    return fs_mainOutput { in1.color };
}

You can see (arrows added by me) how there's an input argument names index now, which causes the name clash. My guess is that name mangling must be applied to prevent this sitution.

cc @berendkleinhaneveld

almarklein avatar Oct 16 '21 11:10 almarklein