I have an AMD Radeon Graphics (Ryzen 7000) GPU and I am creating a program using OpenGL. I wrote the shaders in GLSL version 330
with the extension GL_ARB_shading_language_420pack
enabled. However, when using the ##
operator inside a macro function, I receive the following error:
'##' : not supported for these tokens
The problem still persists even if I use a higher GLSL version, such as 420
. (I am using 330
for compatibility.)
The code in question:
#define calc_channel( n ) \
{ \
vec3 enable_light_rgb = vec3( chan_ctrl##n##_color_light_enable, chan_ctrl##n##_color_light_enable, chan_ctrl##n##_color_light_enable ); \
vec3 light_color_rgb = clamp( diffuse_light.rgb + amb_color##n.rgb * cAmbColor[##n].rgb, 0.0, 1.0 ); \
float light_color_a = clamp( diffuse_light.a + amb_color##n.a, 0.0, 1.0 ); \
color##n##a##n.rgb = chan_ctrl##n##_color.rgb * max( enable_light_rgb, light_color_rgb ); \
color##n##a##n.a = chan_ctrl##n##_alpha.a * max( 1.0 - chan_ctrl##0##_alpha_light_enable, light_color_a ); \
}
Used like this:
calc_channel( 0 );
I use the macro multiple times and not once, hence why it exists. I posted the first occurrence it errors on.
Let me know if any more information is necessary in the comments.
P.S. The code works on other GPUs I have (Nvidia and Intel).
You may have noticed the following copy-paste mistake in the macro function above:
chan_ctrl##0##_alpha_light_enable
This is simply a copy-paste mistake, not an error. It is not the source of the problem as the error still occurs even after replacing it with chan_ctrl0_alpha_light_enable
.
Interestingly, I tried to remove that entire portion of the shader code to see if the rest would compile, and the compiler still chocked on a different macro function that uses ##
, but in a different manner.
The macro function:
#define calc_tex_coord( n ) \
{ \
expand_tex_func( n ); \
tex_coord##n##.x = dot( expand_tex_mtx( n )[ 0 ], tex_coord ); \
tex_coord##n##.y = dot( expand_tex_mtx( n )[ 1 ], tex_coord ); \
float tw = dot( expand_tex_mtx( n )[ 2 ], tex_coord ); \
}
Used like this:
calc_tex_coord( 0 );
The interesting part is the error I get:
ERROR: 0:355: 'tex_coord0nx' : undeclared identifier
ERROR: 0:355: 'tex_coord0ny' : undeclared identifier
ERROR: 0:355: '' : missing #endif
ERROR: 0:355: '' : compilation terminated
ERROR: 4 compilation errors. No code generated.
This time, it did not complain about the ##
operator. However, it incorrectly expanded the tokens tex_coord##n##.x
and tex_coord##n##.y
to tex_coord0nx
and tex_coord0ny
, instead of tex_coord0.x
and tex_coord0.y
.
I got a friend with a different Radeon (AMD Radeon RX 5500 XT) and he was able to get more detailed error messages.
For the first macro function, he got:
Pasting "[" and "0" does not give a valid preprocessing token.
(Note that ##0##
does not error.)
For the second macro function, it actually pasted the 0
(n
) correctly, but still choked on it:
Pasting "tex_coord0" and "." does not give a valid preprocessing token.
Apparently, the AMD preprocessor has an issue with the two following parts:
cAmbColor[##n].rgb
tex_coord##n##.x
In the former, it does not like that ##
is used after [
. In the latter, it does not like that ##
is used before .
.
The common property between both is that AMD the preprocessor does not like pasting a macro argument and a symbol that is not valid for identifiers. I do not know much about the GLSL / C standards to tell whether it is correct or wrong to reject this. However, the matter of fact is that the original code works fine on the preprocessors of Nvidia, Intel, and a third proprietary shader compiler. It is solely the AMD preprocessor that complains.