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.

@Evgeni_Popov @sebavan

Hello guys!

Thanks for caring! You won’t believe how bad is this year for our family already and it’s just June, bad luck on every step… Damned! And you won’t believe how big idiots the teenagers can be, he burnt his body while ‘playing’ with fire with his friends. He will be ok, he is young and he is healing pretty quickly. I promised him to break his arms if I catch him with matches or a lighter ever again! :smiley: The funny thing is that the same shit happened to me when I was 8, but I just burnt my legs :smiley: And my father promised me the same (he owns the copyright). I never ever played with fire again…

Ok, back to the GreasedLine. @Evgeni_Popov I have added grlColorPointers (I think I wil rename it to grlColorIndexes). But the current implementation is vasting resource, because I was using vertexId which values were automatically incremented by the shader I had to create a texture like this:


to achieve this:

the colorIndexes are like this in this case:

From now I am creating the colorIndexes so I can just create a color palette (so the color texture for this line will contain only 4 colors) and point the indexes to the color I want to use. This is quite a big change, I will need keep the colors in the palette unique (even when adding new lines to an existing instance) and recalculate the colorIndexes everytime I add a line. Please be patient :slight_smile: I am already working on it.


1 Like

@Evgeni_Popov @sebavan @Deltakosh


I am in trouble :slight_smile: I spent quite a moment for making the unique color palette with proper color indexes but I’ve introduced a new option called colorsSampling today so you can draw lines with texture sampling of your choice:


I think this is pretty cool to have however if I switch to a unique color palette it will kill this functionality. I think if I just don’t make the palette unique but always append the colors to the palette the colorIndexes interpolation will work. So it requires another round of coding… This will never end :smiley:

It seems to be working :slight_smile:

Lines added to an instance with different color tables and smooth sampling - non lazy - 1 draw call:

The same - lazy - 1 draw call:

Linear sampling - one line - 1 draw call:

Multiple lines - various sampling - 3 draw calls: