Alter the handling of spec consts in non-Vulkan GLSL

Previously, when generating non-Vulkan GLSL, each use of a spec constant
would be subsituted for its default value and the declaration of the constant
itself would be omitted completely.

This change slightly alters this behavior. The uses of the constant are kept,
as well as the declaration, although the latter is stripped of the layout
qualifier. The declaration is also prepended with the following code:

    #ifndef <constant name>_value
    #define <constant name> <default constant value>
    #endif

and the constant itself now looks like

    const <constant type> <constant name> = <constant name>_value;

The rationale for this change is that it gives the user a way to provide
custom values for specialization constants even when the target does not
support them.
This commit is contained in:
Grigory Dzhavadyan 2018-10-29 23:31:32 -07:00 committed by nicebyte
parent dfd1bf8c56
commit a5d82d1138
16 changed files with 266 additions and 79 deletions

View File

@ -1,6 +1,7 @@
#version 310 es
layout(local_size_x = 9, local_size_y = 20, local_size_z = 4) in;
layout(binding = 0, std430) buffer SSBO
{
float a;

View File

@ -1,6 +1,7 @@
#version 450
layout(local_size_x = 1, local_size_y = 2, local_size_z = 3) in;
layout(binding = 0, std430) buffer _6_8
{
float _m0[];

View File

@ -1,16 +1,32 @@
#version 450
#ifndef SPIRV_CROSS_CONSTANT_ID_201
#define SPIRV_CROSS_CONSTANT_ID_201 -10
#endif
const int _7 = SPIRV_CROSS_CONSTANT_ID_201;
#ifndef SPIRV_CROSS_CONSTANT_ID_202
#define SPIRV_CROSS_CONSTANT_ID_202 100u
#endif
const uint _8 = SPIRV_CROSS_CONSTANT_ID_202;
const int _20 = (_7 + 2);
const uint _25 = (_8 % 5u);
const ivec4 _30 = ivec4(20, 30, _20, _20);
const ivec2 _32 = ivec2(_30.y, _30.x);
const int _33 = _30.y;
layout(location = 0) flat out int _4;
void main()
{
vec4 _63 = vec4(0.0);
_63.y = float(((-10) + 2));
_63.y = float(_20);
vec4 _66 = _63;
_66.z = float((100u % 5u));
vec4 _52 = _66 + vec4(ivec4(20, 30, 0, 0));
vec2 _56 = _52.xy + vec2(ivec2(ivec4(20, 30, 0, 0).y, ivec4(20, 30, 0, 0).x));
_66.z = float(_25);
vec4 _52 = _66 + vec4(_30);
vec2 _56 = _52.xy + vec2(_32);
gl_Position = vec4(_56.x, _56.y, _52.z, _52.w);
_4 = ivec4(20, 30, 0, 0).y;
_4 = _33;
}

View File

@ -1,6 +1,12 @@
#version 310 es
layout(local_size_x = 2, local_size_y = 1, local_size_z = 1) in;
#ifndef SPIRV_CROSS_CONSTANT_ID_0
#define SPIRV_CROSS_CONSTANT_ID_0 4.0
#endif
const float X = SPIRV_CROSS_CONSTANT_ID_0;
struct Data
{
float a;
@ -15,7 +21,7 @@ layout(binding = 0, std430) buffer SSBO
void main()
{
Data data[2] = Data[](Data(1.0, 2.0), Data(3.0, 4.0));
Data data2[2] = Data[](Data(4.0, 2.0), Data(3.0, 5.0));
Data data2[2] = Data[](Data(X, 2.0), Data(3.0, 5.0));
_53.outdata[gl_WorkGroupID.x].a = data[gl_LocalInvocationID.x].a + data2[gl_LocalInvocationID.x].a;
_53.outdata[gl_WorkGroupID.x].b = data[gl_LocalInvocationID.x].b + data2[gl_LocalInvocationID.x].b;
}

View File

@ -2,9 +2,15 @@
precision mediump float;
precision highp int;
#ifndef SPIRV_CROSS_CONSTANT_ID_10
#define SPIRV_CROSS_CONSTANT_ID_10 2
#endif
const int Value = SPIRV_CROSS_CONSTANT_ID_10;
layout(binding = 0, std140) uniform SpecConstArray
{
vec4 samples[2];
vec4 samples[Value];
} _15;
layout(location = 0) out vec4 FragColor;

View File

@ -1,9 +1,17 @@
#version 450
#ifndef SPIRV_CROSS_CONSTANT_ID_0
#define SPIRV_CROSS_CONSTANT_ID_0 10u
#endif
const uint s = SPIRV_CROSS_CONSTANT_ID_0;
const bool _13 = (s > 20u);
const uint _16 = _13 ? 30u : 50u;
layout(location = 0) out float FragColor;
void main()
{
FragColor = float((10u > 20u) ? 30u : 50u);
FragColor = float(_16);
}

View File

@ -2,58 +2,138 @@
precision mediump float;
precision highp int;
#ifndef SPIRV_CROSS_CONSTANT_ID_1
#define SPIRV_CROSS_CONSTANT_ID_1 1.0
#endif
const float a = SPIRV_CROSS_CONSTANT_ID_1;
#ifndef SPIRV_CROSS_CONSTANT_ID_2
#define SPIRV_CROSS_CONSTANT_ID_2 2.0
#endif
const float b = SPIRV_CROSS_CONSTANT_ID_2;
#ifndef SPIRV_CROSS_CONSTANT_ID_3
#define SPIRV_CROSS_CONSTANT_ID_3 3
#endif
const int c = SPIRV_CROSS_CONSTANT_ID_3;
const uint _18 = (uint(c) + 0u);
const int _21 = (-c);
const int _23 = (~c);
#ifndef SPIRV_CROSS_CONSTANT_ID_4
#define SPIRV_CROSS_CONSTANT_ID_4 4
#endif
const int d = SPIRV_CROSS_CONSTANT_ID_4;
const int _26 = (c + d);
const int _28 = (c - d);
const int _30 = (c * d);
const int _32 = (c / d);
#ifndef SPIRV_CROSS_CONSTANT_ID_5
#define SPIRV_CROSS_CONSTANT_ID_5 5u
#endif
const uint e = SPIRV_CROSS_CONSTANT_ID_5;
#ifndef SPIRV_CROSS_CONSTANT_ID_6
#define SPIRV_CROSS_CONSTANT_ID_6 6u
#endif
const uint f = SPIRV_CROSS_CONSTANT_ID_6;
const uint _36 = (e / f);
const int _38 = (c % d);
const uint _40 = (e % f);
const int _42 = (c >> d);
const uint _44 = (e >> f);
const int _46 = (c << d);
const int _48 = (c | d);
const int _50 = (c ^ d);
const int _52 = (c & d);
#ifndef SPIRV_CROSS_CONSTANT_ID_7
#define SPIRV_CROSS_CONSTANT_ID_7 false
#endif
const bool g = SPIRV_CROSS_CONSTANT_ID_7;
#ifndef SPIRV_CROSS_CONSTANT_ID_8
#define SPIRV_CROSS_CONSTANT_ID_8 true
#endif
const bool h = SPIRV_CROSS_CONSTANT_ID_8;
const bool _58 = (g || h);
const bool _60 = (g && h);
const bool _62 = (!g);
const bool _64 = (g == h);
const bool _66 = (g != h);
const bool _68 = (c == d);
const bool _70 = (c != d);
const bool _72 = (c < d);
const bool _74 = (e < f);
const bool _76 = (c > d);
const bool _78 = (e > f);
const bool _80 = (c <= d);
const bool _82 = (e <= f);
const bool _84 = (c >= d);
const bool _86 = (e >= f);
const int _92 = int(e + 0u);
const bool _94 = (c != int(0u));
const bool _96 = (e != 0u);
const int _100 = int(g);
const uint _103 = uint(g);
const int _118 = (c + 3);
const int _127 = (c + 2);
const int _135 = (d + 2);
struct Foo
{
float elems[(4 + 2)];
float elems[_135];
};
layout(location = 0) out vec4 FragColor;
void main()
{
float t0 = 1.0;
float t1 = 2.0;
mediump uint c0 = (uint(3) + 0u);
mediump int c1 = (-3);
mediump int c2 = (~3);
mediump int c3 = (3 + 4);
mediump int c4 = (3 - 4);
mediump int c5 = (3 * 4);
mediump int c6 = (3 / 4);
mediump uint c7 = (5u / 6u);
mediump int c8 = (3 % 4);
mediump uint c9 = (5u % 6u);
mediump int c10 = (3 >> 4);
mediump uint c11 = (5u >> 6u);
mediump int c12 = (3 << 4);
mediump int c13 = (3 | 4);
mediump int c14 = (3 ^ 4);
mediump int c15 = (3 & 4);
bool c16 = (false || true);
bool c17 = (false && true);
bool c18 = (!false);
bool c19 = (false == true);
bool c20 = (false != true);
bool c21 = (3 == 4);
bool c22 = (3 != 4);
bool c23 = (3 < 4);
bool c24 = (5u < 6u);
bool c25 = (3 > 4);
bool c26 = (5u > 6u);
bool c27 = (3 <= 4);
bool c28 = (5u <= 6u);
bool c29 = (3 >= 4);
bool c30 = (5u >= 6u);
float t0 = a;
float t1 = b;
mediump uint c0 = _18;
mediump int c1 = _21;
mediump int c2 = _23;
mediump int c3 = _26;
mediump int c4 = _28;
mediump int c5 = _30;
mediump int c6 = _32;
mediump uint c7 = _36;
mediump int c8 = _38;
mediump uint c9 = _40;
mediump int c10 = _42;
mediump uint c11 = _44;
mediump int c12 = _46;
mediump int c13 = _48;
mediump int c14 = _50;
mediump int c15 = _52;
bool c16 = _58;
bool c17 = _60;
bool c18 = _62;
bool c19 = _64;
bool c20 = _66;
bool c21 = _68;
bool c22 = _70;
bool c23 = _72;
bool c24 = _74;
bool c25 = _76;
bool c26 = _78;
bool c27 = _80;
bool c28 = _82;
bool c29 = _84;
bool c30 = _86;
mediump int c31 = c8 + c3;
mediump int c32 = int(5u + 0u);
bool c33 = (3 != int(0u));
bool c34 = (5u != 0u);
mediump int c35 = int(false);
mediump uint c36 = uint(false);
float c37 = float(false);
float vec0[(3 + 3)][8];
float vec1[(3 + 2)];
mediump int c32 = _92;
bool c33 = _94;
bool c34 = _96;
mediump int c35 = _100;
mediump uint c36 = _103;
float c37 = float(g);
float vec0[_118][8];
float vec1[_127];
Foo foo;
FragColor = ((vec4(t0 + t1) + vec4(vec0[0][0])) + vec4(vec1[0])) + vec4(foo.elems[3]);
FragColor = ((vec4(t0 + t1) + vec4(vec0[0][0])) + vec4(vec1[0])) + vec4(foo.elems[c]);
}

View File

@ -1,6 +1,7 @@
#version 310 es
layout(local_size_x = 9, local_size_y = 20, local_size_z = 4) in;
layout(binding = 0, std430) buffer SSBO
{
float a;

View File

@ -1,6 +1,7 @@
#version 450
layout(local_size_x = 1, local_size_y = 2, local_size_z = 3) in;
layout(binding = 0, std430) buffer _6_8
{
float _m0[];

View File

@ -1,16 +1,37 @@
#version 450
#ifndef SPIRV_CROSS_CONSTANT_ID_201
#define SPIRV_CROSS_CONSTANT_ID_201 -10
#endif
const int _7 = SPIRV_CROSS_CONSTANT_ID_201;
#ifndef SPIRV_CROSS_CONSTANT_ID_202
#define SPIRV_CROSS_CONSTANT_ID_202 100u
#endif
const uint _8 = SPIRV_CROSS_CONSTANT_ID_202;
#ifndef SPIRV_CROSS_CONSTANT_ID_200
#define SPIRV_CROSS_CONSTANT_ID_200 3.141590118408203125
#endif
const float _9 = SPIRV_CROSS_CONSTANT_ID_200;
const int _20 = (_7 + 2);
const uint _25 = (_8 % 5u);
const ivec4 _30 = ivec4(20, 30, _20, _20);
const ivec2 _32 = ivec2(_30.y, _30.x);
const int _33 = _30.y;
layout(location = 0) flat out int _4;
void main()
{
vec4 pos = vec4(0.0);
pos.y += float(((-10) + 2));
pos.z += float((100u % 5u));
pos += vec4(ivec4(20, 30, 0, 0));
vec2 _56 = pos.xy + vec2(ivec2(ivec4(20, 30, 0, 0).y, ivec4(20, 30, 0, 0).x));
pos.y += float(_20);
pos.z += float(_25);
pos += vec4(_30);
vec2 _56 = pos.xy + vec2(_32);
pos = vec4(_56.x, _56.y, pos.z, pos.w);
gl_Position = pos;
_4 = ivec4(20, 30, 0, 0).y;
_4 = _33;
}

View File

@ -1,6 +1,12 @@
#version 310 es
layout(local_size_x = 2, local_size_y = 1, local_size_z = 1) in;
#ifndef SPIRV_CROSS_CONSTANT_ID_0
#define SPIRV_CROSS_CONSTANT_ID_0 4.0
#endif
const float X = SPIRV_CROSS_CONSTANT_ID_0;
struct Data
{
float a;
@ -23,7 +29,7 @@ Data combine(Data a, Data b)
void main()
{
data = Data[](Data(1.0, 2.0), Data(3.0, 4.0));
data2 = Data[](Data(4.0, 2.0), Data(3.0, 5.0));
data2 = Data[](Data(X, 2.0), Data(3.0, 5.0));
Data param = data[gl_LocalInvocationID.x];
Data param_1 = data2[gl_LocalInvocationID.x];
Data _73 = combine(param, param_1);

View File

@ -2,9 +2,15 @@
precision mediump float;
precision highp int;
#ifndef SPIRV_CROSS_CONSTANT_ID_10
#define SPIRV_CROSS_CONSTANT_ID_10 2
#endif
const int Value = SPIRV_CROSS_CONSTANT_ID_10;
layout(binding = 0, std140) uniform SpecConstArray
{
vec4 samples[2];
vec4 samples[Value];
} _15;
layout(location = 0) out vec4 FragColor;

View File

@ -1,9 +1,17 @@
#version 450
#ifndef SPIRV_CROSS_CONSTANT_ID_0
#define SPIRV_CROSS_CONSTANT_ID_0 10u
#endif
const uint s = SPIRV_CROSS_CONSTANT_ID_0;
const bool _13 = (s > 20u);
const uint _16 = _13 ? 30u : 50u;
layout(location = 0) out float FragColor;
void main()
{
FragColor = float((10u > 20u) ? 30u : 50u);
FragColor = float(_16);
}

View File

@ -1150,6 +1150,12 @@ struct SPIRConstant : IVariant
// For composites which are constant arrays, etc.
std::vector<uint32_t> subconstants;
// Non-Vulkan GLSL emits defines for each specialization constant,
// and uses them to initialize the constant. This allows the user
// to still be able to specialize the value by supplying corresponding
// preprocessor directives before compiling the shader.
std::string spec_constant_glsl_macro_name;
SPIRV_CROSS_DECLARE_CLONE(SPIRConstant)
};

View File

@ -1710,6 +1710,11 @@ void CompilerGLSL::emit_uniform(const SPIRVariable &var)
statement(layout_for_variable(var), variable_decl(var), ";");
}
string CompilerGLSL::constant_value_macro_name(uint32_t id)
{
return join("SPIRV_CROSS_CONSTANT_ID_", std::to_string(id));
}
void CompilerGLSL::emit_specialization_constant_op(const SPIRConstantOp &constant)
{
auto &type = get<SPIRType>(constant.basetype);
@ -1735,8 +1740,20 @@ void CompilerGLSL::emit_constant(const SPIRConstant &constant)
// Only scalars have constant IDs.
if (has_decoration(constant.self, DecorationSpecId))
{
statement("layout(constant_id = ", get_decoration(constant.self, DecorationSpecId), ") const ",
variable_decl(type, name), " = ", constant_expression(constant), ";");
if (options.vulkan_semantics)
{
statement("layout(constant_id = ", get_decoration(constant.self, DecorationSpecId), ") const ",
variable_decl(type, name), " = ", constant_expression(constant), ";");
}
else
{
const string &macro_name = constant.spec_constant_glsl_macro_name;
statement("#ifndef ", macro_name);
statement("#define ", macro_name, " ", constant_expression(constant));
statement("#endif");
statement("const ", variable_decl(type, name), " = ", macro_name, ";");
statement("");
}
}
else
{
@ -2144,15 +2161,20 @@ void CompilerGLSL::emit_resources()
{
auto &c = id.get<SPIRConstant>();
bool needs_declaration = (c.specialization && options.vulkan_semantics) || c.is_used_as_lut;
bool needs_declaration = (c.specialization) || c.is_used_as_lut;
if (needs_declaration)
{
if (!options.vulkan_semantics)
{
c.spec_constant_glsl_macro_name =
constant_value_macro_name(get_decoration(c.self, DecorationSpecId));
}
emit_constant(c);
emitted = true;
}
}
else if (options.vulkan_semantics && id.get_type() == TypeConstantOp)
else if (id.get_type() == TypeConstantOp)
{
emit_specialization_constant_op(id.get<SPIRConstantOp>());
emitted = true;
@ -2494,7 +2516,7 @@ string CompilerGLSL::to_expression(uint32_t id)
auto &dec = ir.meta[c.self].decoration;
if (dec.builtin)
return builtin_to_glsl(dec.builtin_type, StorageClassGeneric);
else if (c.specialization && options.vulkan_semantics)
else if (c.specialization)
return to_name(id);
else if (c.is_used_as_lut)
return to_name(id);
@ -2507,10 +2529,7 @@ string CompilerGLSL::to_expression(uint32_t id)
}
case TypeConstantOp:
if (options.vulkan_semantics)
return to_name(id);
else
return constant_op_expression(get<SPIRConstantOp>(id));
case TypeVariable:
{
@ -2760,7 +2779,7 @@ string CompilerGLSL::constant_expression(const SPIRConstant &c)
for (auto &elem : c.subconstants)
{
auto &subc = get<SPIRConstant>(elem);
if (subc.specialization && options.vulkan_semantics)
if (subc.specialization)
res += to_name(elem);
else
res += constant_expression(subc);
@ -2781,7 +2800,7 @@ string CompilerGLSL::constant_expression(const SPIRConstant &c)
string res = type_to_glsl(get<SPIRType>(c.constant_type)) + "(";
for (uint32_t col = 0; col < c.columns(); col++)
{
if (options.vulkan_semantics && c.specialization_constant_id(col) != 0)
if (c.specialization_constant_id(col) != 0)
res += to_name(c.specialization_constant_id(col));
else
res += constant_expression_vector(c, col);
@ -3012,7 +3031,7 @@ string CompilerGLSL::constant_expression_vector(const SPIRConstant &c, uint32_t
// Cannot use constant splatting if we have specialization constants somewhere in the vector.
for (uint32_t i = 0; i < c.vector_size(); i++)
{
if (options.vulkan_semantics && c.specialization_constant_id(vector, i) != 0)
if (c.specialization_constant_id(vector, i) != 0)
{
splat = false;
swizzle_splat = false;
@ -3066,7 +3085,7 @@ string CompilerGLSL::constant_expression_vector(const SPIRConstant &c, uint32_t
{
for (uint32_t i = 0; i < c.vector_size(); i++)
{
if (options.vulkan_semantics && c.vector_size() > 1 && c.specialization_constant_id(vector, i) != 0)
if (c.vector_size() > 1 && c.specialization_constant_id(vector, i) != 0)
res += to_name(c.specialization_constant_id(vector, i));
else
res += convert_half_to_string(c, vector, i);
@ -3088,7 +3107,7 @@ string CompilerGLSL::constant_expression_vector(const SPIRConstant &c, uint32_t
{
for (uint32_t i = 0; i < c.vector_size(); i++)
{
if (options.vulkan_semantics && c.vector_size() > 1 && c.specialization_constant_id(vector, i) != 0)
if (c.vector_size() > 1 && c.specialization_constant_id(vector, i) != 0)
res += to_name(c.specialization_constant_id(vector, i));
else
res += convert_float_to_string(c, vector, i);
@ -3110,7 +3129,7 @@ string CompilerGLSL::constant_expression_vector(const SPIRConstant &c, uint32_t
{
for (uint32_t i = 0; i < c.vector_size(); i++)
{
if (options.vulkan_semantics && c.vector_size() > 1 && c.specialization_constant_id(vector, i) != 0)
if (c.vector_size() > 1 && c.specialization_constant_id(vector, i) != 0)
res += to_name(c.specialization_constant_id(vector, i));
else
res += convert_double_to_string(c, vector, i);
@ -3134,7 +3153,7 @@ string CompilerGLSL::constant_expression_vector(const SPIRConstant &c, uint32_t
{
for (uint32_t i = 0; i < c.vector_size(); i++)
{
if (options.vulkan_semantics && c.vector_size() > 1 && c.specialization_constant_id(vector, i) != 0)
if (c.vector_size() > 1 && c.specialization_constant_id(vector, i) != 0)
res += to_name(c.specialization_constant_id(vector, i));
else
{
@ -3164,7 +3183,7 @@ string CompilerGLSL::constant_expression_vector(const SPIRConstant &c, uint32_t
{
for (uint32_t i = 0; i < c.vector_size(); i++)
{
if (options.vulkan_semantics && c.vector_size() > 1 && c.specialization_constant_id(vector, i) != 0)
if (c.vector_size() > 1 && c.specialization_constant_id(vector, i) != 0)
res += to_name(c.specialization_constant_id(vector, i));
else
{
@ -3199,7 +3218,7 @@ string CompilerGLSL::constant_expression_vector(const SPIRConstant &c, uint32_t
{
for (uint32_t i = 0; i < c.vector_size(); i++)
{
if (options.vulkan_semantics && c.vector_size() > 1 && c.specialization_constant_id(vector, i) != 0)
if (c.vector_size() > 1 && c.specialization_constant_id(vector, i) != 0)
res += to_name(c.specialization_constant_id(vector, i));
else
{
@ -3229,7 +3248,7 @@ string CompilerGLSL::constant_expression_vector(const SPIRConstant &c, uint32_t
{
for (uint32_t i = 0; i < c.vector_size(); i++)
{
if (options.vulkan_semantics && c.vector_size() > 1 && c.specialization_constant_id(vector, i) != 0)
if (c.vector_size() > 1 && c.specialization_constant_id(vector, i) != 0)
res += to_name(c.specialization_constant_id(vector, i));
else
res += convert_to_string(c.scalar_i32(vector, i));
@ -3246,7 +3265,7 @@ string CompilerGLSL::constant_expression_vector(const SPIRConstant &c, uint32_t
{
for (uint32_t i = 0; i < c.vector_size(); i++)
{
if (options.vulkan_semantics && c.vector_size() > 1 && c.specialization_constant_id(vector, i) != 0)
if (c.vector_size() > 1 && c.specialization_constant_id(vector, i) != 0)
res += to_name(c.specialization_constant_id(vector, i));
else
res += c.scalar(vector, i) ? "true" : "false";
@ -6913,7 +6932,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
case OpBitwiseXor:
{
auto type = get<SPIRType>(ops[0]).basetype;
GLSL_BOP_CAST(^, type);
GLSL_BOP_CAST (^, type);
break;
}

View File

@ -391,6 +391,7 @@ protected:
void emit_flattened_io_block(const SPIRVariable &var, const char *qual);
void emit_block_chain(SPIRBlock &block);
void emit_hoisted_temporaries(std::vector<std::pair<uint32_t, uint32_t>> &temporaries);
std::string constant_value_macro_name(uint32_t id);
void emit_constant(const SPIRConstant &constant);
void emit_specialization_constant_op(const SPIRConstantOp &constant);
std::string emit_continue_block(uint32_t continue_block);