-
-
Notifications
You must be signed in to change notification settings - Fork 21.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
GDShader preprocessor evaluates weird functions in #if
condition expressions
#96504
Comments
I didn't check, but I assume current implementation may be using something like Expression? |
Another issue related to
//shader_type spatial;
#if defined(foo) && foo
const int one = 1;
#endif
#if !defined(foo) || foo
const int two = 2;
#endif
cd /tmp
nano a.c # edit the files
cat a.c > a.frag; echo '=== GLSL ==='; glslang -E a.frag; echo '=== C ==='; gcc -E a.c GLSL (and C of course) allow it, deactivating the first const int two = 2; GDShader raises "Condition evaluation error" on both You can tell the operators have short-circuit semantics because without the preceding But note that it seems only parameter-less macros are "syntactically" allowed after expansion. If the right part is So this is what I think GLSL is doing:
|
Just found out about the //shader_type spatial;
#if !defined apple && defined banana
const int zero = 0;
#elif !defined apple && !defined banana
const int one = 1;
#endif C and GLSL accept it just fine. GDShader raises "Condition evaluation error". |
Tested versions
System information
Godot v4.3.stable (77dcf97) - Freedesktop SDK 23.08 (Flatpak runtime) - X11 - Vulkan (Forward+) - integrated Intel(R) HD Graphics 5500 (BDW GT2) - Intel(R) Core(TM) i5-5300U CPU @ 2.30GHz (4 Threads)
Issue description
In GDShader
#if
condition expressions, you can use several operators (more than I expected it to allow) and even functions (e.g. math likesqrt
,sin
), which will be evaluated in the preprocessor. Which ones are undocumented.At first I expected those to at least match the GDShader functions and operator syntax. But I found it's not always the case (e.g. ternary
? :
doesn't work,inversesqrt(...)
doesn't either).After some more tests (see #96253 (comment) for background), I found it's accepting functions in
@GlobalScope
as well as some constructors likebool
etc. It allows even functions very weird to allow, likerandf
,instance_from_id
andrid_from_int64
.Allowing even stuff like
bytes_to_var_with_objects
seems like it could be particularly dangerous (ACE risk?).But I don't know for sure to which extent it allows functions with side-effects and whether it affects the editor.
In any case, I'm surprised things like functions work at all. I was expecting that dealing with integers and booleans would be enough for a preprocessor. In fact, if the intention is to match C/GLSL, then GDShader is doing way more than it should in the preprocessor
#if
directives. Not even C deals with float or boolean constants in the preprocessor, let alone math functions. GLSL doesn't either. They do handle integers without theu
suffix (so nouint
support).C does handle arbitrary names, treating them like
0
(eventrue
is treated like0
), but GLSL doesn't allow them on#if
.GDShader allows most literals (bool, int_decimal, int_hex, uint_decimal, float), except for uint_hex like
0x0u
.Comments from @pirey0:
IMO, GDShader should match GLSL, and be as safe as possible:
0
true
isn't a keyword, it won't expand to0
by default; raise "undefined macro" error instead&&
and||
) and the final#if
expression boolean resultu
suffixdefined(macro_name)
(alsodefined macro_name
) preprocessor keyword is the only "function" allowedA lot of these behaviors are explicitly defined in the GLSL ES 3.00 spec pages 13~14.
Moved from #96253 (sub-issue 7).
Steps to reproduce
bug-global-fn-evaluation.gdshader
Minimal reproduction project (MRP)
N/A
The text was updated successfully, but these errors were encountered: