stackgl / glsl-transpiler

Transpile GLSL to JS
http://stackgl.github.io/glsl-transpiler/
175 stars 22 forks source link

Weird behaviour when reusing the `compile` function #57

Open geoffreytools opened 12 months ago

geoffreytools commented 12 months ago

Hey,

I am using glsl_transpiler with great effect to unit test my shaders and something puzzles me.

After reading the readme I got this impression that I could reuse the function compile that is returned by GLSL, like so:

var compile = GLSL({
    uniform: function (name) {
        return `uniforms.${name}`
    },
    attribute: function (name) {
        return `attributes.${name}`
    }
})

const a = compile(something);
const b = compile(somethingElse);

However when I do this I realise the behaviour is inconsistent: sometimes my glsl functions are suffixed with their types (for example vec2 getPosition(float index, float length) gets renamed to getPosition_float_float in the emitted Javascript) and sometimes they are not (they are not overloaded, at least not the ones I am currently testing). Whether they are renamed or not depends on evaluation order: the first compilation has no suffixes and subsequent compilations have some, at least from what I have seen.

As a workaround I simply call GLSL each time I want to compile, then my glsl functions are never renamed, but I don't know if this is the intended behaviour.

I usually run the same shader with different static variables (to be used in loops for example) which I inject with a simple template and find/replace logic, so the same functions are compiled multiple times:

// with the aforementioned workaround
export const compile = (shaderStr, map = {}) => GLSL({
    uniform: name => `uniforms.${name}`,
    attribute: name => `attributes.${name}`
})(replaceMap(shaderStr, map))

const replaceMap = (str, map) => {
    return str.replace(
        new RegExp(Object.keys(map).join("|"), "gi"),
        function(match) {return String(map[match]);}
    );
}

Hope this is useful to you. Even without reusing the compile function I don't have to complain about performance, so this is not a pressing issue but it's a little weird.

tchuss

dy commented 10 months ago

Hi @geoffreytools! The thing is all 500+ tests are using single GLSL instance and never produce artifacts that you mention, and tbh I don't know where that may be coming from, so I am afraid without more specific reproduction case I won't be able to help. I just tested what you showed and it works fine:

    var compile = GLSL({
        uniform: function (name) {
            return `uniforms.${name}`
        },
        attribute: function (name) {
            return `attributes.${name}`
        },
        version: '300 es'
    })
    const a = compile(`vec2 getPosition(float index, float length); getPosition(0, 1);`);
    const b = compile(`vec2 getPosition(float index, float length); getPosition(0, 1);`);
    console.log(a, b)
dy commented 10 months ago

Usually you see *_float_float when function overload takes place. Maybe issue is somewhere there. eg.

    vec4 f(in float x) {
        return vec4(x);
    }

    vec4 f(in float x, in float y) {
        return vec4(x, x, y, y);
    }

I will try to check