KhronosGroup / glslang

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

Vulkan GLSL: Partially specialized floating-point vectors are not supported. #1074

Closed Themaister closed 5 years ago

Themaister commented 7 years ago

Vulkan GLSL supports partially specializing a vector:

    While SPIR-V specialization constants are only for scalars, a vector
    can be made by operations on scalars:

        layout(constant_id = 18) const int scX = 1;
        layout(constant_id = 19) const int scZ = 1;
        const vec3 scVec = vec3(scX, 1, scZ);  // partially specialized vector

However, this shader fails to compile:

#version 310 es
precision mediump float;

layout(constant_id = 3) const float c0 = 10.0;
layout(constant_id = 4) const float c1 = 20.0;
const vec3 v0 = vec3(c0, c1, 30.0);

layout(location = 0) out vec4 FragColor;

void main()
{
    FragColor = v0.xyzz;
}
test.frag
ERROR: test.frag:6: '=' : global const initializers must be constant ' const mediump 3-component vector of float'
ERROR: 1 compilation errors.  No code generated.
johnkslang commented 5 years ago

Note that the integer equivalent is supported:

const ivec3 scVec = ivec3(scX, 1, scZ);  // partially specialized vector

This generates correct SPIR-V with a specialization constant vector. Will look into why floating point is treated differently.

johnkslang commented 5 years ago

This is as specified in KHR_vulkan_glsl:

The allowed specialization operator white list for producing a specialization constant includes these:

  • int(), uint(), and bool() constructors for type conversions from any of the following types to any of the following types:
    • int
    • uint
    • bool
  • vector versions of the above conversion constructors

But, not the floating-point variants.

So, the expression vec3(scX, 1, scZ) is not a specialization constant, making it a non-constant.

This could instead, if needed, be filed as a feature request against GLSL/Vulkan.