laurentlb / shader-minifier

Minify and obfuscate GLSL or HLSL code
https://ctrl-alt-test.fr/minifier/
Apache License 2.0
446 stars 33 forks source link

Function already defined (error C1013) on minifying a working GLSL shader #316

Open technolizer opened 1 year ago

technolizer commented 1 year ago

I have a rather big shader with lots of small functions (600+ lines) that is working correctly before running the minifying tool on it. When I minify it I get this error of duplicate functions: 0(434) : error C1013: function "d" is already defined at 0(427) Those are literally two consecutive functions in the file and the second function is calling the first one. If I rename the second function to 'dd' in the minified file the code compiles ok. Unfortunately I cannot provide the whole code and I couldn't yet reproduce it in a simpler example. Could it be that it's running out of symbols/letters?

vec2 d(float v,float i,float z,inout int y,int f) { if(v<i) y=f; float m=clamp(.5-.5(i-v)/z,0.,1.); return vec2(max(i,v)+zmin(m,1.-m),1-m); } vec2 d(float v,float i,float f,inout int z,int y) { return d(v,-i,f,z,y); }

laurentlb commented 1 year ago

Thanks for the report, this is surprising. Can you look at the functions before minification, and check their signature? They have exactly the same list of arguments?

technolizer commented 1 year ago

They do, since func2 calls func1 with its parameters. I marked the functions here (it was easy to find correspondence since the code that follows is pretty unique in the shader): image

technolizer commented 1 year ago

I tested a few more things and it does compile if I replace the 'dd' with some single-letters: tried all from 'a' to 'z' and about 6-7 of them work.

As additional information, the original shader does not contain any preprocessor directives: so no #if #ifdef #ifndef #define

If I come up with any new information or with an example that I can post here I will let you know.

On my side the workaround is to replace that function in 2 places every time i generate a minified shader using different versions of my original code (I have to generate about 8-16 shaders, and once that's done I'm all good to use the minified ones).

technolizer commented 9 months ago

After some time I also realized that some functionality was missing because of a switch that was missing break; after a return value; (this does not happen if all cases have return value; instead of break;) Not yet sure if it's related to previous issue, but I will recheck with the breaks added everywhere image

update: the problems with switch/case seem a bit more complicated here, managed to change the code so that it properly minifies that function - but the other issue hasn't disappeared once this was fixed (so they are not related)

laurentlb commented 9 months ago

Thanks for the report, this is very useful! We've just investigated, it's a bug in the parser, that leads to funny things in the inlining and renaming passes.

Workaround: use curly braces after each case:

  switch (array)
  {
    case aSDFRotY:   { fRepRot(q.zx, step.w, step.xy); break; }
  }
laurentlb commented 9 months ago

The switch/case issue should be fixed with #319.

technolizer commented 8 months ago

Thank you for the case fix!

As for the issue with duplicate functions I managed to bypass it. I had a lot of pairs of functions like these two with the same name but different nb of arguments and different return type: float fOp(float a, float b) vec2 fOp(float a, float b, int idA, int idB)

I simply renamed the ones returning a vec2 with **vOp*****

and that fixed it. The weird part is that it was duplicating a few functions only in the more complex shaders... but all had the same function definitions and all were using them so it's really hard to say what the cause is.

Anyway, thanks again for all the help and a great piece of software.