shader-slang / slang

Making it easier to work with shaders
MIT License
1.79k stars 160 forks source link

Add compile flag to allow for relaxed enum rules #4298

Closed chaoticbob closed 3 weeks ago

chaoticbob commented 1 month ago

When compiling shader source that's shared between multiple platforms, it would be useful to have a compiler flag to relax the enum rules in Slang to do the following:

  1. Allow unscoped enum usage without the explicit [UnscopedEnum] attribute
  2. Allow usage of anonymous enums

Compilers for other platforms may not be able to ignore unknown attributes resulting in a compile error. In some cases it not be desirable or infeasible for someone to modify their shader code base to adhere to Slang's requirements for scoped enums.

jkwak-work commented 1 month ago

Can you give us more example? I am not sure what can happen on different platforms. If we are gonna work on it, we need a repro case.

chaoticbob commented 1 month ago

Sure thing. Here's a shader that's accepted by DXC for both unscoped and anonymous enums:

cbuffer MyBuffer {
    int Select1;
    int Select2;
};

// Unscoped enum
enum MyEnum {
    First = 1,
    Second = 2,
};

// Anonymous enum
enum {
    Third = 1,
    Fourth = 2,
};

float4 main(float4 P: SV_POSITION) : SV_TARGET
{
    return ((Select1 == First) || (Select2 == Third)) ? float4(1, 0, 0, 0) : float4(0, 1, 0, 0);
}

If this source is shared between DXC and Slang, currently an #ifdef would be required to tag MyEum with an [UnscopedEnum] attribute. This would fail to compile on DXC:

C:\local\Temp\6333300a-e80d-4b9b-9a7f-a03fc3083fd6.hlsl:7:1: error: an attribute list cannot appear here
[UnscopedNum]

Also Slang doesn't accept the anonymous enum, which would result in a compiler error on the Slang side:

enums.slang(14): error 20001: unexpected '{', expected identifier
enum {

A compiler flag to allow Slang to accept unscoped and anonymous enums would go a long way in shared shader source.

chaoticbob commented 2 weeks ago

Should also cover this case:

struct TestStruct {
    enum EnumInTestStruct {
        A = 1,
    };
};

TestStruct::EnumInTestStruct testFunc() {
    return TestStruct::A;
}

uint PSMain() : SV_TARGET
{
    TestStruct::EnumInTestStruct i = testFunc();
    return (int)i;
}