Skip to content

Incorrect spirv generated #9073

@kobli

Description

@kobli

Issue Description

The code below produces probably incorrect spirv. Vulkan pipeline creation fails, spirv-val produces following output:

error: line 100: Indexes passed to OpAccessChain must be of type integer.
  %321 = OpAccessChain %_ptr_Function_uint %320 %316

Reproducer Code

static const uint MAX_NESTED_VOLUMES = 4;
static const int MATERIAL_LAYERS_MAX = 10;

struct MaterialFlags
{
    static const uint32_t HAS_SCATTERING_VOLUME = 1 << 20;
};

struct Material
{
    uint32_t flags = 0;
    uint32_t layerCount = 0;
    uint32_t layers[MATERIAL_LAYERS_MAX];

    bool HasFlag(uint32_t mask)
    {
        return (flags & mask) != 0;
    }

    IVolume GetVolume()
    {
        if (HasFlag(MaterialFlags::HAS_SCATTERING_VOLUME)) {
            return ScatteringVolume(PhaseFunction());
        }
        else {
            return EmptyVolume();
        }
    }
};

[[vk::binding(1, 3)]]
StructuredBuffer<Material> materials;

struct PhaseFunction
{
    void GenerateSample(uint channelIndex, float2 rnd, inout float3 sampleDirection, out float pdf)
    {
        sampleDirection = {};
        pdf = {};
    }
}

interface IVolume
{
    void Integrate(float3 rayOrigin, float3 intersection, float4 rnd, inout float3 rayDirection, inout float tHit,
                   inout float3 throughput);
}

struct EmptyVolume : IVolume
{
    float3 dummy1 = 0;

    void Integrate(float3 rayOrigin, float3 intersection, float4 rnd, inout float3 rayDirection, inout float tHit,
                   inout float3 throughput)
    {
    }
}

struct ScatteringVolume : IVolume
{
    PhaseFunction phase;

    __init(PhaseFunction phase)
    {
        this.phase = phase;
    }

    void Integrate(float3 rayOrigin, float3 intersection, float4 rnd, inout float3 rayDirection, inout float tHit,
                   inout float3 throughput)
    {
        let rayDirectionBeforeScatter = rayDirection;
        float phasePdf;
        phase.GenerateSample(0, rnd.zw, rayDirection, phasePdf);
        tHit = 0;
    }
}

struct Payload
{
    float2 _padding;
    float tHit;
    int volumeStackIndex;

    uint volumeStack[MAX_NESTED_VOLUMES];

    IVolume GetVolume()
    {
        if (volumeStackIndex == -1)
            return EmptyVolume();
        uint mid = volumeStack[volumeStackIndex];
        return materials[mid].GetVolume();
    }
}

[shader("closesthit")]
void main(inout Payload payload, in BuiltInTriangleIntersectionAttributes attr)
{
    float3 throughput = 1;
    IVolume volume = payload.GetVolume();
    float3 o = {};
    volume.Integrate(WorldRayOrigin(), {}, {}, o, payload.tHit, throughput);
}

compiled with
slangc.exe -entry main test.slang -o test.spv

Expected Behavior

The code should compile and pass spirv-val.

Environment

  • Slang Version 2025.18 up to 2025.22.1 (2025.17.3 and older worked fine)

Metadata

Metadata

Assignees

Type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions