-1

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).

EDIT

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.

EDIT 2

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.
AboodXD
  • 148
  • 9
  • If the question is going to be downvoted, I would appreciate if a comment would be added detailing why and how it can be improved. – AboodXD Jun 26 '23 at 16:44

2 Answers2

0

It looks like the AMD preprocessor only supports using ## where one of the operands of the operator is a parameter of the macro, which is strictly correct per C and GLSL language specs. Your macro has the expression:

chan_ctrl##0##_alpha_light_enable

which attempts to paste some tokens that don't include the argument. If your replace that with

chan_ctrl0_alpha_light_enable

it will probably work.

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226
  • Hello. Thanks for your answer. I have actually caught this instance and fixed it, but forgot to update the question text. However, this was not the source of the error and it still occurs. Also, I found another interesting case and I will be updating the question with it. – AboodXD Jun 26 '23 at 14:32
  • Question updated. – AboodXD Jun 26 '23 at 14:57
-1

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.

AboodXD
  • 148
  • 9
  • 1
    Per the C (preprocessor) spec if the result of concatenating the characters in the tokens before and after the `##` operators is not a (single) valid token, the result is undefined. Most preprocessors will simply retokenize the character sequence, and if that results in multiple tokens it is fine. It looks like AMD's preprocessor is detecting the case where it is not a single token and flagging it as an error. – Chris Dodd Jun 26 '23 at 23:02
  • @ChrisDodd that seems to be the case. Nice catch. – AboodXD Jun 27 '23 at 00:22
  • GLSL 330 specification states: `Two tokens in a macro can be concatenated into one token using the token pasting (##) operator, as is standard for C++ preprocessors. The result must be a valid single token, which will then be subject to macro expansion. ` – racz16 Jun 28 '23 at 15:49