KhronosGroup / glslang

Khronos-reference front end for GLSL/ESSL, partial front end for HLSL, and a SPIR-V generator.
Other
3.01k stars 831 forks source link

HLSL: Buffer variable assignation #881

Open glare42 opened 7 years ago

glare42 commented 7 years ago

Hi,

consider the following valid HLSL shader:

Buffer g_buffer1;
Buffer g_buffer2;

float4 FetchFromBuffer(bool condition) {
    Buffer myBuf;
    if( condition )
    {
        myBuf = g_buffer1;
    }
    else
    {
        myBuf = g_buffer2;
    }

    return myBuf[0];
}

float4 main() : SV_TARGET0
{
    return FetchFromBuffer( true );
}

glslang will return those errors on compilation:

ERROR: repro.txt:8: 'assign' : l-value required "myBuf" (can't modify a sample r) ERROR: repro.txt:8: '' : could not create assignment ERROR: repro.txt:8: 'then statement' : Expected repro.txt(8): error at column 20, HLSL parsing failed. ERROR: 4 compilation errors. No code generated.

glare42 commented 7 years ago

Additional information, the following code doesn't raise the issue:

Buffer g_buffer1;
Buffer g_buffer2;

float4 FetchFromBuffer(bool condition) {
    Buffer myBuf = condition ? g_buffer1 : g_buffer2;
    return myBuf[0];
}

float4 main() : SV_TARGET0
{
    return FetchFromBuffer( true );
}

When keeping the literal evaluation on the same line as the local variable declaration, it seems ok. I guess this is an issue with lexing of the HLSL not being able to evaluate the literal directly ? Could we expect a fix about that ?

johnkslang commented 7 years ago

Stock Vulkan can't variably select between two such objects such that when a static access is done, it does not know which one it is. (Arrays of some objects is the exception, with a variable index.)

In fact, the HLSL language itself seems a bit ill-defined here. Sometimes myBuf and 'g_buffer*` are being treated as a pointer (a copy is not really being made, only a copy of a pointer), and sometimes as an object (when referenced).

It seems possible though, that using the SPV_KHR_variable_pointers extension, this code could be compiled.

johnkslang commented 7 years ago

Actually, FXC seems to have this problem in general too: I get

error X3669: Resources being indexed cannot come from conditional expressions, they must come from literal expressions.

I see now this issue's subject is only relevant to propagation of compile-time constants.

That is, MS is basically relying on an optimization pass being applied to eliminate illegal constructs. To get glslang to the same place, we need SPIR-V -> SPIR-V transform for both inlining and/or constant propagation, processing non-Vulkan-legal SPIR-V in the meantime.