Apparent C vs GLSLang preprocessor differences
https://c.godbolt.org/z/9zYTvWcqM
#include "stdio.h"
#include "stdbool.h"
#define CONCAT3_IMPLX(x, y, z) x##y##z
#define CONCAT3_IMPL1(x, y, z) CONCAT3_IMPLX(x, y, z)
#define CONCAT3_IMPL0(x, y, z) CONCAT3_IMPL1(x, y, z)
#define CONCAT3(x, y, z) CONCAT3_IMPL0(x, y, z)
#define USE_FOO_PUSH_CONSTANTS true
#define THING_NAME FOO
#if CONCAT3(USE_,THING_NAME,_PUSH_CONSTANTS) == true
void Foo() { puts("It worked"); }
#else
void Foo() { puts("It didn't work"); }
#endif
int main() {
Foo();
return 0;
}
Program returned: 0
Program stdout
It worked
vs
https://glsl.godbolt.org/z/6ofsE9Es8
// This will be consumed as a .glsl file and needs the stage and target profile. Example options:
// -S comp --target-env vulkan1.2
#version 450
#extension GL_EXT_shader_explicit_arithmetic_types_int32 : require
#define U32 uint32_t
#define CONCAT3_IMPLX(x, y, z) x##y##z
#define CONCAT3_IMPL1(x, y, z) CONCAT3_IMPLX(x, y, z)
#define CONCAT3_IMPL0(x, y, z) CONCAT3_IMPL1(x, y, z)
#define CONCAT3(x, y, z) CONCAT3_IMPL0(x, y, z)
#define USE_FOO_PUSH_CONSTANTS true
#define THING_NAME FOO
#if CONCAT3(USE_,THING_NAME,_PUSH_CONSTANTS) == true
U32 Foo() { return 1; }
#else
U32 Foo() { return 0; }
#endif
void main() {
U32 a = Foo();
}
<source>
<source>:17: '#if' : unexpected tokens following directive
<source>:17: '' : missing #endif
<source>:17: '' : compilation terminated
3 compilation errors. No code generated.
Linking compute stage: Missing entry point: Each stage requires one entry point
SPIR-V is not generated for failed compile or link
Compiler returned: 2
nani
From the GLSL spec, I don't think true is defined in the GLSL preprocessor:
- Expressions following #if and #elif are further restricted to expressions operating on literal integer constants, plus identifiers consumed by the defined operator.
- Character constants are not supported.
So, I'm guessing it's the comparison of true == true that is failing. If you changed it to #if defined(CONCAT3(USE_,THING_NAME,_PUSH_CONSTANTS)) does it work correctly?
nope, that doesn't work for anything
https://c.godbolt.org/z/jT1YM848c
#include "stdio.h"
#include "stdbool.h"
#define CONCAT3_IMPLX(x, y, z) x##y##z
#define CONCAT3_IMPL1(x, y, z) CONCAT3_IMPLX(x, y, z)
#define CONCAT3_IMPL0(x, y, z) CONCAT3_IMPL1(x, y, z)
#define CONCAT3(x, y, z) CONCAT3_IMPL0(x, y, z)
#define USE_FOO_PUSH_CONSTANTS true
#define THING_NAME FOO
#if defined(CONCAT3(USE_,THING_NAME,_PUSH_CONSTANTS))
void Foo() { puts("It worked"); }
#else
void Foo() { puts("It didn't work"); }
#endif
int main() {
Foo();
return 0;
}
<source>:13:20: error: missing ')' after "defined"
13 | #if defined(CONCAT3(USE_,THING_NAME,_PUSH_CONSTANTS))
| ^
<source>:13:21: error: missing binary operator before token "USE_"
13 | #if defined(CONCAT3(USE_,THING_NAME,_PUSH_CONSTANTS))
| ^~~~
https://glsl.godbolt.org/z/YzPjEfMno
// This will be consumed as a .glsl file and needs the stage and target profile. Example options:
// -S comp --target-env vulkan1.2
#version 450
#extension GL_EXT_shader_explicit_arithmetic_types_int32 : require
#define U32 uint32_t
#define CONCAT3_IMPLX(x, y, z) x##y##z
#define CONCAT3_IMPL1(x, y, z) CONCAT3_IMPLX(x, y, z)
#define CONCAT3_IMPL0(x, y, z) CONCAT3_IMPL1(x, y, z)
#define CONCAT3(x, y, z) CONCAT3_IMPL0(x, y, z)
#define USE_FOO_PUSH_CONSTANTS true
#define THING_NAME FOO
#if defined(CONCAT3(USE_,THING_NAME,_PUSH_CONSTANTS))
U32 Foo() { return 1; }
#else
U32 Foo() { return 0; }
#endif
void main() {
U32 a = Foo();
}
<source>
<source>:17: 'preprocessor evaluation' : expected ')'
<source>:17: '#if' : unexpected tokens following directive
<source>:17: '' : missing #endif
<source>:17: '' : compilation terminated
4 compilation errors. No code generated.
Linking compute stage: Missing entry point: Each stage requires one entry point
if I try using 1|0 instead of true|false, C works, but GLSL still fails
https://c.godbolt.org/z/qvK1azjxn
#include "stdio.h"
#include "stdbool.h"
#define CONCAT3_IMPLX(x, y, z) x##y##z
#define CONCAT3_IMPL1(x, y, z) CONCAT3_IMPLX(x, y, z)
#define CONCAT3_IMPL0(x, y, z) CONCAT3_IMPL1(x, y, z)
#define CONCAT3(x, y, z) CONCAT3_IMPL0(x, y, z)
#define USE_FOO_PUSH_CONSTANTS 1
#define THING_NAME FOO
#if CONCAT3(USE_,THING_NAME,_PUSH_CONSTANTS) == 1
void Foo() { puts("It worked"); }
#else
void Foo() { puts("It didn't work"); }
#endif
int main() {
Foo();
return 0;
}
Program returned: 0
Program stdout
It worked
https://glsl.godbolt.org/z/Gn8Y7YW5G
// This will be consumed as a .glsl file and needs the stage and target profile. Example options:
// -S comp --target-env vulkan1.2
#version 450
#extension GL_EXT_shader_explicit_arithmetic_types_int32 : require
#define U32 uint32_t
#define CONCAT3_IMPLX(x, y, z) x##y##z
#define CONCAT3_IMPL1(x, y, z) CONCAT3_IMPLX(x, y, z)
#define CONCAT3_IMPL0(x, y, z) CONCAT3_IMPL1(x, y, z)
#define CONCAT3(x, y, z) CONCAT3_IMPL0(x, y, z)
#define USE_FOO_PUSH_CONSTANTS 1
#define THING_NAME FOO
#if CONCAT3(USE_,THING_NAME,_PUSH_CONSTANTS) == 1
U32 Foo() { return 1; }
#else
U32 Foo() { return 0; }
#endif
void main() {
U32 a = Foo();
}
<source>
<source>:17: '#if' : unexpected tokens following directive
<source>:17: '' : missing #endif
<source>:17: '' : compilation terminated
3 compilation errors. No code generated.
Linking compute stage: Missing entry point: Each stage requires one entry point
SPIR-V is not generated for failed compile or link
Compiler returned: 2
May or may not warrant a separate issue, but I've run into the preprocessor differences again with this example:
https://c.godbolt.org/z/7G65Yx3aM
#define _CONCAT_IMPLX(x, y) x##y
#define _CONCAT_IMPL1(x, y) _CONCAT_IMPLX(x, y)
#define _CONCAT_IMPL0(x, y) _CONCAT_IMPL1(x, y)
#define CONCAT(x, y) _CONCAT_IMPL0(x, y)
// X macro
#define XS \
X(VALUE, int, foo, 0) \
X(VALUE, int, bar, 0)
// Define each X to actually be a specialized macro based on the 'kind_' parameter
#define X(kind_, type_, name_, defaultValue_) \
CONCAT(X_,kind_)(type_, name_, defaultValue_)
// said specialized macro, only one variant is needed to demonstrate the issue
#define X_VALUE(type_, name_, defaultValue_) 1 &&
// the macros should be expanded so this value is '(1 && 1 && 1)`, which evaluates true
#define SHARED_TYPE_IS_POD (XS 1)
void main() {
#if SHARED_TYPE_IS_POD
return;
#else
return;
#endif
}
Compiler returned: 0
https://glsl.godbolt.org/z/avqacq6oc
// This will be consumed as a .glsl file and needs the stage and target profile. Example options:
// -S comp --target-env vulkan1.1
#version 450
#define _CONCAT_IMPLX(x, y) x##y
#define _CONCAT_IMPL1(x, y) _CONCAT_IMPLX(x, y)
#define _CONCAT_IMPL0(x, y) _CONCAT_IMPL1(x, y)
#define CONCAT(x, y) _CONCAT_IMPL0(x, y)
// X macro
#define XS \
X(VALUE, int, foo, 0) \
X(VALUE, int, bar, 0)
// Define each X to actually be a specialized macro based on the 'kind_' parameter
#define X(kind_, type_, name_, defaultValue_) \
CONCAT(X_,kind_)(type_, name_, defaultValue_)
// said specialized macro, only one variant is needed to demonstrate the issue
#define X_VALUE(type_, name_, defaultValue_) 1 &&
// the macros should be expanded so this value is '(1 && 1 && 1)`, which evaluates true
#define SHARED_TYPE_IS_POD (XS 1)
void main() {
#if SHARED_TYPE_IS_POD
return;
#else
return;
#endif
}
<source>
<source>:25: 'preprocessor evaluation' : expected ')'
<source>:25: '#if' : unexpected tokens following directive
<source>:25: '' : missing #endif
<source>:25: '' : compilation terminated
4 compilation errors. No code generated.
SPIR-V is not generated for failed compile or link
Compiler returned: 2