WebGPU flat in/out shader variable

Hi guys!

How can I make a varying (out/in) variable flat in WebGPU?


flat out int vertexId;
vertexId = gl_VertexID;


flat in int vertexId;

works in WebGL2, but throws this error in WebGPU:
ERROR: 0:213: 'location' : SPIR-V requires location for user input/output

I have a solution in my mind to leave out the flat modifier and pass the value as float and round the value in the fragment shader but I believe there is a better way.

Thank you!

I made some more tests, tried to use different keywords, but I think the shader compiler can’t deal with the interpolation specifier correctly.

This PR will fix the problem:

However, you’ll need to use the “varying” keyword in vertex and fragment shaders instead of “out”/“in” for this to work with both WebGL and WebGPU.

After the PR is merged, this PG will work:

1 Like

Thank you!


It seems that there is an issue with the flat qualifier on Windows/WebGL2 as well. It gets lost/ignored.

How can I debug/view the compiled shader?

I did something like this:

        const efs = engine._compiledEffects
        for(const eff in efs) {
            const e = efs[eff]
            console.log('_fragmentSourceCode', e._fragmentSourceCode)
            console.log('_fragmentSourceCodeBeforeMigration', e._fragmentSourceCodeBeforeMigration)
            console.log('_vertexSourceCodeBeforeMigration', e._vertexSourceCodeBeforeMigration)
            console.log('_rawVertexSourceCode', e._rawVertexSourceCode)
            console.log('_rawFragmentSourceCode', e._rawFragmentSourceCode)

The first two console logs contains the flat out/in stuff but the others don’t. Can you please shed a bit light on this, what is what, how to get the compiled shaders correctly…

Thank you!

This is what I get on Windows/WebGL2:

This is what I get on Mac/WebGL2, exactly same source (this is correct):

The variable is defined as
flat out int grlColorPointer and flat in int grlColorPointer

The flat qualifier is in the final shaders in this PG:

From Spector:



Would you have a repro that I could have a look at?

1 Like

I can’t see any differences in your code compared to my code regarding the flat variable… I will modify your PG to use a material plugin to get to the closest I can to my implementation.


I need your help :slight_smile: I set up the shader like this:

flat varying int grlColorPointer;
grlColorPointer = int(gl_VertexID);

I have a mesh with 6 vertices so the half must be rendered in green the other half in red if using this code in fragment shader:

vec4 grlColor = vec4(0.,1.,0.,1.);
if (grlColorPointer <= 3) {
   grlColor = vec4(1.,0.,0.,1.);
gl_FragColor = grlColor;

WebGL, as expected:


Same shader, no errors.

Do you have any ideas what can be different in two engines?

I am afraid that the only way to try it out is to clone my repo at GitHub - RolandCsibrei/Babylon.js: Babylon.js is a powerful, beautiful, simple, and open game and rendering engine packed into a friendly JavaScript framework.

Thank you very much!

Here are two simple repros:

WebGL: https://playground.babylonjs.com/#6GFJNR#199
WebGPU: https://playground.babylonjs.com/?webgpu#6GFJNR#199

I put the question to the matrix channel, waiting for answers (I had no luck in the WebGPU channel, I’m now trying Dawn).

Ok, that’s interesting…

By default, WebGL uses the last vertex as the “provoking vertex”, i.e. the vertex that provides the attribute value to be used when this value is not interpolated (“flat varying”).

WebGPU (and everyone else, it seems) uses the first vertex instead.

There’s a WebGL extension, WEBGL_provoking_vertex that lets you change the “provoking vertex”.

By using the extension to define the first vertex as the provoking vertex, we get the same result as with WebGPU:

This extension is fairly recent (upgraded to “community approved” in January 2023), so I don’t think you can really rely on it…

In your case, the best solution is probably to create a new attribute (or use an existing attribute if you still have room for a float) that would contain the vertex index. This way, you don’t depend on how the triangle is rasterized under the hood.

1 Like

Thank you very much for the answer! I was already thinking about a new attribute but was curious what the heck is happening :slight_smile:

The gl.getExtension('WEBGL_provoking_vertex') throws an error in my browser Version 114.0.5735.91

Another reason to not use it :slight_smile:

1 Like

I already had some sort of counter for dashing and I successfuly used it to look up the color texture (just had to modify the color texture a bit). So no new attribute is needed.


Thanks once again!

Ok, just realized that it won’t work with lines added to an a previous instance, because the dash counter is relative to the line not to the mesh created from several lines… So the new attribute is needed.

My kid is in hospital, I can’t do anything meaningful now. I’ll get back to GreasedLine in a few days, when he gets out of the worst… Sorry.

No need to apologize, really, take care of your kid, I hope he gets better soon!

So sorry to hear that… My thoughts to you and your family.