KhronosGroup / glslang

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

nonuniformEXT not working correctly in conditionals #3561

Open manas-kulkarni opened 3 months ago

manas-kulkarni commented 3 months ago

Spirv generated is not valid when nonuniformEXT is used in ternary condition or even if/else condition. Issue happens when nonuniformEXT is used for the texture index. If nonuniformEXT is used for the sampler, then the spirv is generated correctly. But according to Vulkan spec https://github.com/KhronosGroup/GLSL/blob/main/extensions/ext/GL_EXT_nonuniform_qualifier.txt nonuniformEXT can be used for local variables as well.

GLSL

#version 450
#extension GL_EXT_nonuniform_qualifier : require

layout(constant_id = 0) const uint gCondition = 1u;

layout(set = 0, binding = 2, std430) readonly buffer type_StructuredBuffer_uint
{
    uint _m0[];
} sb;

layout(set = 0, binding = 0) uniform texture2D gTextures[];
layout(set = 0, binding = 1) uniform sampler st;

layout(location = 0) in vec2 in_var_TEXCOORD0;
layout(location = 0) out vec4 out_var_SV_TARGET0;

void main()
{
    uint _38 = uint(in_var_TEXCOORD0.x);
    uint _13 = (sb._m0[_38] * 1000u);
    uint _14 = (sb._m0[_38]);
    if (gCondition != 0)
    {
        out_var_SV_TARGET0 = texture((sampler2D(gTextures[nonuniformEXT(_13)], st)), in_var_TEXCOORD0);
    }
    else
    {
        out_var_SV_TARGET0 = texture((sampler2D(gTextures[nonuniformEXT(_14)], st)), in_var_TEXCOORD0);
    }
}

Command line

glslangValidator.exe -V a.glsl -S frag

Decompile spirv using spirv-cross

spirv-cross.exe .\frag.spv --output frag.glsl --vulkan-semantics

Resulting GLSL has no nonuniformEXT instructions

#version 450
#extension GL_EXT_nonuniform_qualifier : require

layout(constant_id = 0) const uint gCondition = 1u;

layout(set = 0, binding = 2, std430) readonly buffer type_StructuredBuffer_uint
{
    uint _RESERVED_IDENTIFIER_FIXUP_m0[];
} sb;

layout(set = 0, binding = 0) uniform texture2D gTextures[];
layout(set = 0, binding = 1) uniform sampler st;

layout(location = 0) in vec2 in_var_TEXCOORD0;
layout(location = 0) out vec4 out_var_SV_TARGET0;

void main()
{
    uint _RESERVED_IDENTIFIER_FIXUP_38 = uint(in_var_TEXCOORD0.x);
    uint _RESERVED_IDENTIFIER_FIXUP_13 = sb._RESERVED_IDENTIFIER_FIXUP_m0[_RESERVED_IDENTIFIER_FIXUP_38] * 1000u;
    uint _RESERVED_IDENTIFIER_FIXUP_14 = sb._RESERVED_IDENTIFIER_FIXUP_m0[_RESERVED_IDENTIFIER_FIXUP_38];
    if (_RESERVED_IDENTIFIER_FIXUP_38 != 0u)
    {
        uint _48 = _RESERVED_IDENTIFIER_FIXUP_13;
        out_var_SV_TARGET0 = texture(sampler2D(gTextures[_48], st), in_var_TEXCOORD0);
    }
    else
    {
        uint _62 = _RESERVED_IDENTIFIER_FIXUP_14;
        out_var_SV_TARGET0 = texture(sampler2D(gTextures[_62], st), in_var_TEXCOORD0);
    }
}
nanokatze commented 3 months ago

There's a bug in how you're applying nonuniformEXT, see https://github.com/KhronosGroup/Vulkan-Samples/blob/main/shaders/descriptor_indexing/nonuniform-quads.frag#L33-L39

manas-kulkarni commented 3 months ago

Thanks. Would it be possible for the tools to warn about this?

nanokatze commented 3 months ago

I'm the wrong person to ask that but I also wouldn't hold my breath