Repository: shader-slang/slang
File: source/slang/slang-reflection-api.cpp (C++)

Code before:
    SlangUInt axisCount,
    SlangUInt* outSizeAlongAxis)
{
    auto entryPointLayout = convert(inEntryPoint);

    if (!entryPointLayout)
        return;
    if (!axisCount)
        return;
    if (!outSizeAlongAxis)
        return;

    auto entryPointFunc = entryPointLayout->entryPoint;
    if (!entryPointFunc)
        return;

    SlangUInt sizeAlongAxis[3] = {1, 1, 1};

    auto astBuilder = entryPointLayout->program->getLinkage()->getASTBuilder();
    SLANG_AST_BUILDER_RAII(astBuilder);

    // First look for the HLSL case, where we have an attribute attached to the entry point function
    auto numThreadsAttribute = entryPointFunc.getDecl()->findModifier<NumThreadsAttribute>();
    if (numThreadsAttribute)
    {
        foldThreadGroupSizeExtents(
            numThreadsAttribute->extents,
            numThreadsAttribute->specConstExtents,
            astBuilder,
            entryPointFunc,
            entryPointLayout->program,
            sizeAlongAxis);
    }

    // If no HLSL [numthreads] was found, check for the GLSL case where
    // layout(local_size_x = N) is attached to a sibling EmptyDecl in the
    // same parent scope.
    if (!numThreadsAttribute)
    {
        if (auto localSizeAttr = findGLSLLocalSizeAttribute(entryPointFunc.getDecl()))
        {
            foldThreadGroupSizeExtents(
                localSizeAttr->extents,
                localSizeAttr->specConstExtents,
                astBuilder,
                entryPointFunc,
                entryPointLayout->program,
                sizeAlongAxis);
        }
    }


Review comment (suggestion):
I'm not really sure whether this approach is quite correct. I would have fixed this in the compiler elsewhere such that `NumThreadsAttribute` for the entry point would be updated from the GLSL declarations. This would have fixed the root cause.

Patching up this is the reflection API means we still have two sources of truth in the compiler. And hence, it feels like a workaround rather than a fix.

Code after:
    //

    if (axisCount > 0)
        outSizeAlongAxis[0] = sizeAlongAxis[0];
    if (axisCount > 1)
        outSizeAlongAxis[1] = sizeAlongAxis[1];
    if (axisCount > 2)
        outSizeAlongAxis[2] = sizeAlongAxis[2];
    for (SlangUInt aa = 3; aa < axisCount; ++aa)
    {
        outSizeAlongAxis[aa] = 1;
    }
}

SLANG_API void spReflectionEntryPoint_getComputeWaveSize(
    SlangReflectionEntryPoint* inEntryPoint,
    SlangUInt* outWaveSize)
{
    auto entryPointLayout = convert(inEntryPoint);

    if (!entryPointLayout)
        return;
    if (!outWaveSize)
        return;

    auto entryPointFunc = entryPointLayout->entryPoint;
    if (!entryPointFunc)
        return;

    // First look for the HLSL case, where we have an attribute attached to the entry point function
    if (auto waveSizeAttribute = entryPointFunc.getDecl()->findModifier<WaveSizeAttribute>())
    {
        if (auto cint = entryPointLayout->program->tryFoldIntVal(waveSizeAttribute->numLanes))
            *outWaveSize = (SlangUInt)cint->getValue();
        else if (waveSizeAttribute->numLanes)
            *outWaveSize = 0;
    }
}

SLANG_API int spReflectionEntryPoint_usesAnySampleRateInput(SlangReflectionEntryPoint* inEntryPoint)
{
    auto entryPointLayout = convert(inEntryPoint);
    if (!entryPointLayout)
        return 0;

    if (entryPointLayout->profile.getStage() != Stage::Fragment)
        return 0;

    return (entryPointLayout->flags & EntryPointLayout::Flag::usesAnySampleRateInput) != 0;
}