KhronosGroup/WebGL

EXT_provoking_vertex for WebGL2

Opened this issue ยท 15 comments

I don't think there's ever been a provoking vertex extension for OpenGL ES, but being able to control the provoking vertex convention has a unique applicability to WebGL2 as a way of improving the efficiency of flat-shaded rendering on certain platforms.

Flat-shaded rendering with the "provoking vertext last" convention must be supported by WebGL2 implementations, but some implementations that layer it on top of graphics APIs that only support the "provoking vertex first" convention have to emulate this behavior, so there's no way for an application to tell if it will be efficient. If running on a WebGL2 implementation that supported an optional extension similar to EXT_provoking_vertex, an application could be confident that flat-shaded rendering with the "provoking vertex first" convention would be efficient. If not, it could fall back to using index buffers built for the "provoking vertex last" convention, which would likely be efficient if said extension were widely implemented on platforms where that convention had to be emulated.

At one point Firefox's WebRender module started using a PROVOKING_VERTEX_DONT_CARE hack, so the applicability is real.

These days WR does this, which has a similar effect to what you want, I think:
https://searchfox.org/mozilla-central/rev/0e93b94f4c2045c6a5f5260ee48bbf7a94a993bc/gfx/wr/webrender/src/device/gl.rs#1431

        if supports_extension(&extensions, "GL_ANGLE_provoking_vertex") {
            gl.provoking_vertex_angle(gl::FIRST_VERTEX_CONVENTION);
        }

@kdashg Yes, that's a good example of what I had in mind! It's good to see that ANGLE supports an extension like this already, though it doesn't look like it's implemented for the Metal backend yet.

I think the most appealing part of the extension is (for firefox's usecase here) ANGLE only exposes the extension when it's beneficial to use the extension to switch from LAST (ES3) to FIRST (D3D, etc).

I think that's what we'd want to target here too, where we'd only want to encourage switching (via supplying an extension) in cases where it's beneficial to switch. It looks like Metal is also FIRST, so it's an easy fix there. (ANGLE must have done heroics already to make Metal behave as if LAST-provoked, so they'd just have to be able to disable it)

I agree. As far as I know, Direct3D and Metal are the two backends that have to emulate LAST_VERTEX_CONVENTION today and would therefore benefit from this.

Sorry to ask here. But its hard to find any info on this on the web. Does anyone know if its possible to trigger a PROVOKING_VERTEX_DONT_CARE or similar hack on Safari / WebKit on Metal?

The emulation in Metal of LAST_VERTEX_CONVENTION slows performance of a similar scene to ~1% of the original performance without the flat attribute. It makes it completely impossible to pass ints to fragments.

As of today, only the extension spec and the CTS are ready. Browser implementations are still work-in-progress.

I read https://registry.khronos.org/webgl/extensions/WEBGL_provoking_vertex/ and I have a question about it:

Suppose I really need flat for my app , but im ready for a fallback to usual interpolation in case of deoptimization.

The extension is available if browser supports it AND first_vertex is better.

However, I cannot distinguish two cases:

  1. browser doesnt support extension
  2. last_Vertex is better.

I really need it because in case 1 i can just enable fallback and in case 2 i don't have to enable it.

When a browser does not support the extension, LAST_VERTEX should not cause performance issues and could be used as usual.

And how do I distinguish this from usual case "this browser version is old and slows down the app" ? Should I track what minimal version of specific browser has the implementation and detect version by user-agent? Good^W old practice in browser world.

UPD. I tried to find WebGLProvokingVertex type in global scope, but its not there :( Extension types dont exist in global, only stuff like WebGLUniformLocation exists...

Ok, so as I understand it you have two different shaders:

  1. flat shader using the flat modifier,
  2. A "fake-flat" shader not using the flat modifier but some other workaround.

For all devices which support flat and has the WebGL expected provoking vertex OR has defined the EXT_PROVOKING_VERTEX you want to use the flat shader.

For devices which emulate the provoking vertex spec, there is no way to identify these without profiling in the current WebGL2 spec afaik. Safari 16.2 on iPad has no way of telling me that it emulates provoking vertex behavior. When looking for the EXT_PROVOKING_VERTEX in Safari 16.2 it will return nothing. The absence of the ext does not indicate that the device does not emulate vertex-order.

Is there a way to know if Vertex_Order is emulated in a browser/device, and use a fallback shader for just those browsers/devices?

Is there a way to know if Vertex_Order is emulated in a browser/device, and use a fallback shader for just those browsers/devices?

Exactly. Thank you for unrolling that!

kdashg commented

And how do I distinguish this from usual case "this browser version is old and slows down the app" ? Should I track what minimal version of specific browser has the implementation and detect version by user-agent? Good^W old practice in browser world.

That would be all you can do, yes.

Is there a way to know if Vertex_Order is emulated in a browser/device, and use a fallback shader for just those browsers/devices?

OK, my question is a bit different - if browser already can expose extension if needed, but it doesnt expose it - Is there a way to determine whether its old browser that can limit performance of my app, or new one that doesn't inform me because it should be ok. Kelsey answered that :)

kdashg commented

My advice would be to check for the extension, and use that if it's useful. Otherwise, do the workaround checking you were previously doing. (which might be "no workaround, it's just slow until users/browsers update")