-
-
Notifications
You must be signed in to change notification settings - Fork 735
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WebGL 1 phase out #3947
Comments
@HarelM you asked previously:
I think the answer is no. To really benefit from WebGL 2 one has to write different shaders as far as I understand. |
I think this is the correct link for said feature: https://caniuse.com/webgl2 |
Wait ... I thought webgpu is the future and webgl 1 and 2 are going away anyways ... |
Yes, webgpu is the future, but we can't sunset webgl until one day when webgpu is sufficiently supported. We currently have superficial webgl2 support, with a webgl1 fallback, and this fallback is kinda blocking us from adopting any webgl2-only features, like layout qualifiers, UBOs, to begin refactoring of the codebase towards something a little closer to what webgpu will require. Thus dropping webgl1 could narrow the gap and act as a stepping stone towards webgpu. Dropping webgl1 would make the adapter layer that sits on top of webgl and webgpu simpler. Case in point, when the "modularization" refactor started in MapLibre Native to preparing for adding Metal, the first thing that happened was upgrading the OpenGL implementation from OpenGL 2 (~webgl1) to OpenGL 3+ (~webgl2) as it was easier to then abstract over Metal & OpenGL3 than Metal & OpenGL2. It's of course important that webgl2 is as well supported as webgl1 is for the browser versions we support, so that it doesn't lead to issues for visitors (like anyone using safari on ios <=14), so there is a balance there we always need to gauge. |
Related to: |
Hey @birkskyum, I'm curious if you'd appreciate public community contributions in this area. We have forked and removed WebGL1 compatibility layer and turned implementation into WebGL2 only. It involved modifying shader transpiler and changing existing shaders ever so slightly but overall, it was not a huge refactor. If you'd be open to taking a look and potentially merging a PR that removes WebGL1 and its compatibility layer entirely in favor of WebGL2 (after a thorough review and testing of course), we're more than willing to contribute. If not, I'm wondering what's the plan before #4511 because I also think there should be an intermediate step between WebGL1/2 -> Modular Backend where we can just rely on WebGL2 only, leverage WebGL2 more before transitioning into wider a Modular Backend. |
I've discussed this in the last open visualization summit in London with the deck.gl team, I believe the way forward would be to use luma.gl from the deck.gl stack to abstract the webgl layer to allow future supports of webgpu. This however, requires to sunset webgl 1 as they did in deck.gl as well. |
Basically, as soon as webgl1 is removed from this line, it'll be webgl2 only. Lines 3059 to 3061 in 5638bd1
|
@HarelM thanks for the quick reaction, I appreciate it. In this repo codebase, removing WebGL1 does not require full rewrite of all existing shaders, it's actually quite minimal. There are only a few places to remove in the TypeScript source and perhaps update a few types (like WebGLContext to WebGL2Context etc.). We have tried to rely on deck.gl and luma.gl more but there are some clever implementations in this codebase and maplibre-gl-js turned out to be much more performant, especially on mobile devices. I don't think we'd like to jump fully into luma.gl/deck.gl anytime soon. There are some cool use-cases for deck.gl as an "enhancement" layer but definitely wouldn't replace base maplibre-gl-js map layer (which we tried to do). @birkskyum also thanks for jumping in quickly. If you don't mind, we can work on a PR and quickly put it up for review on you. Runtime-wise, you're correct that we could just switch over to WebGL2Rendering context rest of the runtime code would simply render with WebGL2 onto the canvas. However, there are some legacy places we need to follow-up on and slightly update shader code as well. Here's one in the // WebGL1 Compat -- Start
if (type === 'fragment') {
code = code
.replace(/\bin\s/g, 'varying ') // For fragment shaders, replace "in " with "varying "
.replace('out highp vec4 fragColor;', '');
}
if (type === 'vertex') {
code = code
.replace(/\bin\s/g, 'attribute ') // For vertex shaders, replace "in " with "attribute "
.replace(/\bout\s/g, 'varying '); // For vertex shaders, replace "out " with "varying "
}
code = code
.replace(/fragColor/g, 'gl_FragColor')
.replace(/texture\(/g, 'texture2D(');
// WebGL1 Compat -- End This block should be removed, There are some other super minor changes like using I guess, nevertheless, I'll talk with my other colleague and put up a PR very soon, hopefully we can discuss there in more technical terms and I'll link it back to this issue. |
@0xFA11 I didn't mean you should switch to use deck.gl I meant we should look into using luma.gl inside maplibre as the abstraction layer for webgl/gpu. |
@HarelM It might be a good exercise to use luma.gl underneath maplibre-gl-js, maybe we can actually adopt and integrate it in isolation as part of Modular Backend target. However, with all due respect, I disagree with you about WebGL1 removal. As someone linked in this thread, there are some archaic browsers and platforms that could only run WebGL1 and I really do not think people are actually using maplibre-gl-js inside those browsers. Removing WebGL1 compat and consolidating on WebGL2 would not reduce compiled javascript output size but it would allow us to leverage so many things in WebGL2 with maplibre-gl-js whilst staying fully compatible and without #if macros or other extra conditional code. Do you mind chiming in a bit @PhantomCloak? |
I agree with @0xFA11 that enabling WebGL2 by removing WebGL1 compat will benefit to leveraging modern graphics techniques. This change benefits both users who want to utilize modern GLSL features without forking and those forked maplibre-gl-js for more advanced use cases, while also making easier to implement specific WebGL2 features to existing code base. Such as the pixel derivative functions Another more advanced example might be the MRT (Multiple Render Targets) feature which WebGL1 doesn't offer any alternatives. It enables to implement deferred rendering techniques for high-performance effects e.g writing layer data to an render target which can be used for the shading various feature groups roads, buildings, etc. The current code base already have frame buffer objects, and enabling WebGL2 will pave the way for scenarios involving multiple framebuffer objects in the future. Another extra win might be in the fill-extrusion layer, due to WebGL1's hard constraint of 16-bit indices we had to batch them below that limit. In the future, this could be extended to 32-bit indices in WebGL2, simplifying some of the logic. Overall, I think it's a worthwhile effort considering the possibilities it brings compared to it's surface area |
I've been reviewing every PR that was made to this repo for the past few years. I'm not sure how this reads, and I did not mean to offend anyone with what I wrote, if I did, I'm sorry. |
This is absolutely, 100% no doubt our intention here, I'm not sure why you seem to think and feel the other way. In fact, our fork is public under my name here: https://github.com/0xFA11/maplibre-gl-js , not only that we are in the middle of trying to implement high-precision line drawing, outline for fill-extrusion layers, more accurate 3d lighting with direction lights and some other performance optimizations into the maplibre-gl-js. We will also move our public fork of this repo into another place, under our organization, still as a public fork of this repository with plans to continually contribute changes, fixes, optimizations in public with PRs back targeting this repository. We are doing all of this work on our own, in public, will continue to do so in public, willing to contribute back without asking anything in exchange. Moreover, @PhantomCloak is our R&D engineer, doing paid work, the work being "improve maplibre-gl-js and keep maintaining compatibility by making minimal changes". Quite literally, I was about to create a task specifically for this WebGL1 removal work, again, all in good-faith, with public open-source contribution in mind. For WebGL2 consolidation, there are more and more arguments we could elaborate here but we wanted to actually elaborate on them when @PhantomCloak creates the PR and we'd discuss more technical stuff over there in details. FWIW, I want to mention just 1 example here,
In this case specifically, pack/unpack built-in functions would be fantastic to have! Personally, I can emphatize and relate to maintaining a public project and seeing some random people demanding work and other things while contributing little to zero back, I've been in that place in the past but honestly, we're not those people, we love and want to contribute back, this thread is one of the first examples of that — we're trying to figure out how we could contribute back without implementing specific things for our case but implement things more broadly then specialize for our stuff in our projects for our own needs. I hope this helps and gives you more context about where we're coming from. |
I might be understanding this the wrong way, but "be a good exercise" sounds like this is something you wouldn't want to do. In any case, I'd be happy to review any PR you'd like to push in order to modernize the codebase/infrastructure. Before opening a PR, I would recommend showing a design document (can be a post here, a discussion, a draft PR with no implementation etc) of what you are planning to do (assuming it's not a trivial fix), otherwise you might fall in love with the solution, which may cause a harder code review process, which I would like to avoid. I didn't look into the implementation details of luma.gl, but I believe it should be the way forward, if you don't think this is the case, I would recommend writing what are the pros and cons of each direction to modernize the infrastructure layer around different GPU backends and we can discuss how to proceed from here. Any support and contribution is very well welcomed, and if for any reason it didn't sound like I appreciate it, then I apologize, open source is at the very core of what we do and we would like to welcome anyone to join in. |
I created a draft PR #5165 to illustrate what it'd take to consolidate on WebGL2, I also commented a few things inline on the PR itself. Having said that, there are at least 2 remaining follow-up tasks we would consider:
About this:
We are actually willing to commit to Modular Backend goal, including reassesing luma.gl and we tried to use deck.gl + luma.gl on top of maplibre-gl-js base map layer for extruded buildings. We experimented with WebGPU after it became enabled by default on iOS 18.2 Let me elaborate and share our journey for more context. We used deck.gl's MVTLayer and tried to apply image effects from luma.gl on top of the final render. We tried both Overlaid and Interleaved deck.gl rendering on top of maplibre-gl-js but they were simply not performant enough for us on mobile. The main difference came down to maplibre-gl-js batching all extruded buildings into one vertex array and render them in one single draw call vs MVTLayer in deck.gl rendering every individual geometry feature one by one, resulting in 20-30k draw calls per tile (depending on which city you're looking at etc.). In theory, we could either rewrite MVTLayer or write a brand-new layer similar to MVTLayer that would do something similar to what maplibre-gl-js does for tiles: batch all extruded buildings' vertices into one large vertex array and call draw on them for the whole tile's vertex, meaning 1 drawcall per tile for all extruded buildings resulting in 1 triangulated geometry drawn with shader in one go. That is still possible but more and more, we actually think we could elevate maplibre-gl-js up to modern WebGL2 runtime and write shaders natively in maplibre-gl-js rather than rendering another canvas (Overlaid) or middle layer (Interleaved) alongside with maplibre-gl-js. Rendering maplibre-gl-js only, by design, will always outperform maplibre-gl-js + deck.gl or any other additional renderers. The case for luma.gl only is also an interesting one and we're definitely interested, including the committement to experiment with the idea and potentially propose it as "the Modular Backend" layer for maplibre-gl-js if we find success. Main problem right now is that it's a huge committement to the codebase since it'd touch basically everywhere in the maplibre-gl-js rendering code: styles, painters, buckets, projections and everything in between. If I understand you correctly @HarelM and if I extrapolate a bit on what you said, you wouldn't like the idea of introducing a huge codebase rewrite+refactor in order to adopt luma.gl as the backend, at least not in 5.0.0 this year but would be open to it next year, right? If so, we think the same, hence why we're trying to write shaders in maplibre-gl-js directly with WebGL2 instead. From our perspective and experience so far, we think that WebGL1 to WebGL2 would be a good middleground, an intermediate step between WebGL1 -> Modular WebGL2/WebGPU backend where we could still enjoy and support the existing user base. We want to use maplibre-gl-js only for almost everything, including custom shaders and visualizations, rather than doing for an extra solution like deck.gl or kepler.gl — not because we don't like them, because at large scale, they are not performant enough. We can bake similar features (layers and shaders) directly into maplibre-gl-js with WebGL2 even without fully committing to luma.gl yet. We particularly loved deck.gl's lighting and real-time shadows, we'd more than happy to use deck.gl for extruded buildings only on top of maplibre-gl-js but again, at every building in every tile and city scale, it simply fall short on mobile and not performant enough. It'd be amazing if we could write similar shaders (almost like real-time game engine shaders) in maplibre-gl-js directly, and we would maybe have directional lights, cascaded shadows (real-time or baked), SSAO/HBAO, rounded soft corners etc. I will reach out to @PhantomCloak some time today or early next week to add screenshots from our demos, debugging sessions and comparisons. We will also elaborate why they were achievable with WebGL2 but were not possible to achieve with WebGL1. Let's keep the conversation going, I think we will end up in a positive and constructive place. |
I'll elaborate a bit and try to clarify what I said: |
thank you for the clarification and giving us more context about what you folks have in mind.
for these points, I guess we will just disagree unfortunately. that's ok, we're obviously biased towards all the good stuff we're planning implement with WebGL2 (ambient occlusion, cascaded shadows, post-processing effects with MRT etc.) before the full WebGPU or luma.gl transition.
to this, I can say it's definitely more than a month, actually more than 2 months as well. we tried to use luma.gl directly without deck.gl in maplibre-gl-js but ended up falling back to deck.gl as an overlay or interleaved layer on top of maplibre-gl-js base layer, due to complexity and amount of places it touched in the maplibre-gl-js rendering pipeline. so, my suggestion would be to treat it as a major feature that'd fall out of this year for sure. for the draft PR #5165, I think we can still find a middle ground there. we don't have to make maplibre-gl-js WebGL2 exclusive but I think we can and should make it WebGL2-exclusive-compatible, in other words, we should be able to at least disable WebGL1 -> WebGL2 translator (for that, apply fixes in the draft PR today, if you'd think turning PR #5165 into "feat: WebGL2 exclusive mode with WebGL2 shaders" that'd skip WebGL2 -> WebGL1 downgrade, we're more than happy to do the work and contribute that back. that would not break anybody's codebase, give us an intermediate step before WebGPU/luma.gl or any other modular backend solution while still allowing folks like us to write more ambitious shaders directly within maplibre-gl-js more efficiently rather than reaching out to an external solution like deck.gl or kepler.gl — what do you think? |
No doubt, this is a bug that should be fixed, no argue here.
I think this is a good idea how to solve this and be able to move forward. I would also like to see the following get integrated as part of this change/RP: i.e. create a separate config object for all configuration related to webgl now and allow to easily extend it in the future, hopefully. |
Fantastic! We will look into #5135 as well and see if we can combine both that option and WebGL2Only option in one go. The only question I have in my mind right now is "how to skip WebGL1 conversion?" because it's happening at build/publish time. FWIW, we will be following WebGPU and/or luma.gl roadmap closely. We might end up commenting on PRs or contribute some PRs back if we can get luma.gl as a backend before anybody else. We were not 100% sure if it'd be desirable, let alone achievable without dramatically refactoring and rewriting maplibre-gl-js rendering pipeline — perhaps we can follow your footsteps along the way if that's the ultimate plan. |
Yeah, I thought about this build time issue, creating two separate build outputs is not a great solution, and both outputs will increase package size, which is also not desired. |
I mean, I agree, I like the idea. String replacement at runtime on the original shader source wouldn't be too bad since it'd happen once during map load. That would make them watchable and ultimately make it easier to switch between WebGL1 and WebGL2 at runtime — also package size will be smaller too. We will figure out a way and come back. |
I've just timed this and converting the whole shader folder (i.e. 35 vertex and 32 fragment shaders) takes 4ms. |
Not that I think the results would change much, but it might be a good idea to time it on a mobile device, just to be on the safe side... |
This is a tracking issue to discuss the removal of WebGL 1. At the moment, there are no concrete plans of doing this as far as I understand, but it is good to have a centralized place for the arguments on removing WebGL 1...
The text was updated successfully, but these errors were encountered: