Skip to content

HLSL compiled to SPIR-V on Metal - must use 'struct' tag to refer to type 'X' in this scope #2597

@StrongJoshua

Description

@StrongJoshua

Hi,

I have a project that I have primarily been working on in Windows (also using Vulkan) where I have an HLSL fragment shader that I compile to SPIR-V using shaderc, and then use in a Vulkan pipeline via SDL3. On Windows, everything works fine. However, after recently starting some work from MacOS (Sequoia 15.6.1) I am running into these errors when building the pipeline:

[mvk-error] VK_ERROR_INITIALIZATION_FAILED: Shader library compile failed (Error code 3):
program_source:67:44: error: must use 'struct' tag to refer to type 'world_info' in this scope
    constant auto& world_info = *(constant world_info* )((constant char* )spvDescriptorSet3.world_info + spvDynamicOffsets[0]);
                                           ^
                                           struct 
program_source:67:20: note: struct 'world_info' is hidden by a non-type declaration of 'world_info' here
    constant auto& world_info = *(constant world_info* )((constant char* )spvDescriptorSet3.world_info + spvDynamicOffsets[0]);
                   ^
program_source:68:44: error: must use 'struct' tag to refer to type 'frame_info' in this scope
    constant auto& frame_info = *(constant frame_info* )((constant char* )spvDescriptorSet3.frame_info + spvDynamicOffsets[1]);
                                           ^
                                           struct 
program_source:68:20: note: struct 'frame_info' is hidden by a non-type declaration of 'frame_info' here
    constant auto& frame_info = *(constant frame_info* )((constant char* )spvDescriptorSet3.frame_info + spvDynamicOffsets[1]);
                   ^
.
[mvk-error] VK_ERROR_INITIALIZATION_FAILED: Fragment shader function could not be compiled into pipeline. See previous logged error.

Here's the snippet defining those variables in my fragment shader in HLSL:

struct WorldInfo {
    float4 ambient_light;
    float2 world_resolution;
    float2 level_size;
};

struct FrameInfo {
    float2 world_offset;
    uint num_lights;
};

ConstantBuffer<WorldInfo> world_info : register(b0, space3);
ConstantBuffer<FrameInfo> frame_info : register(b1, space3);

And here is the compiled shader code when running with the MVK_CONFIG_LOG_LEVEL=3 MVK_CONFIG_DEBUG=1 options (you can see that the struct names WorldInfo andFrameInfo are ignored):

struct world_info
{
    float4 ambient_light;
    float2 world_resolution;
    float2 level_size;
};

struct frame_info
{
    float2 world_offset;
    uint num_lights;
};

...

struct spvDescriptorSetBuffer3
{
    constant void* _m0_pad [[id(0)]];
    constant world_info* world_info [[id(1)]];
    constant frame_info* frame_info [[id(2)]];
};

struct main0_out
{
    float4 _entryPointOutput [[color(0)]];
};

struct main0_in
{
    float2 input_uv [[user(locn0)]];
};

fragment main0_out main0(main0_in in [[stage_in]], constant spvDescriptorSetBuffer2& spvDescriptorSet2 [[buffer(2)]], constant spvDescriptorSetBuffer3& spvDescriptorSet3 [[buffer(3)]], constant uint* spvDynamicOffsets [[buffer(30)]])
{
    constant auto& world_info = *(constant world_info* )((constant char* )spvDescriptorSet3.world_info + spvDynamicOffsets[0]);
    constant auto& frame_info = *(constant frame_info* )((constant char* )spvDescriptorSet3.frame_info + spvDynamicOffsets[1]);

As you can see from the error. The actual struct definition in the compiled code shares the name of the variable (and I verified that changing the struct name does not at all affect the generated code).

I saw this issue also referenced in #2380, but unlike what that poster claimed, the issue does not appear to be related to storage buffers, rather uniform buffers (ConstantBuffer).

Vulkan Instance Version: 1.4.321

Metadata

Metadata

Assignees

No one assigned

    Labels

    SPIRV-CrossPlease re-submit to SPRIV-Cross

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions