Skip to content
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

Lack of support for partial WebGL buffer updates (delta-updates) #110

Closed
JannikGM opened this issue Mar 19, 2021 · 10 comments
Closed

Lack of support for partial WebGL buffer updates (delta-updates) #110

JannikGM opened this issue Mar 19, 2021 · 10 comments
Labels

Comments

@JannikGM
Copy link
Contributor

Currently the WebGL buffers are very naive and they are always updated completly. Some API like the feature-states can be used to update individual features, however, even if a single feature is touched, the entire bucket gets reuploaded.

There should be a dirty-bitmap (or similar) which keeps track of dirty buffer regions, so that larger buffer updates can be skipped.

@lseelenbinder
Copy link
Member

It's often quite difficult to do this due to the GPU/CPU memory boundary control issues (I've run into similar issues in other projects). Also, if any features change, the size and layout of the buffer may need to change, as well. Are you aware of a good way to handle / implement this in WebGL? (My GL experience is not in WebGL.)

@JannikGM
Copy link
Contributor Author

It's often quite difficult to do this due to the GPU/CPU memory boundary control issues (I've run into similar issues in other projects).

I assume you mean the issue where updating a buffer that's currently in use will stall the GPU?
- I don't think I've ever ran into this issue on modern drivers, but I'm also not sure how D3D11 ANGLE would deal with it (ANGLE is by far the most used backend for our products).

If this turns out the be a problem we could probably go back to the technique of having 2 swapping buffers so we can update a copy that isn't currently in use.

Also, if any features change, the size and layout of the buffer may need to change, as well.

Ofcourse - if the layout changes, then there's no way to delta-update.

This whole discussion is primarily about changes due to setFeatureState on a specific feature.
We use this to mark specific features on hover, similar to this mapbox sample: https://docs.mapbox.com/mapbox-gl-js/example/hover-styles/

Are you aware of a good way to handle / implement this in WebGL? (My GL experience is not in WebGL.)

I'm also only starting with WebGL, but I have a background in OpenGL and OpenGL ES, too.


I also didn't measure if there was actually any performance issue with buffer-updates at the moment.
But looking at the code, it's weird to see these full buffer updates. I've also seen many different websites with hundreds of symbols per tile, so I'd assume that updating all the buckets isn't the smartest thing to do.

There are definitely more pressing issues, but I'd like to have these things documented and to get early feedback (maybe someone already tried it or has experience with it).

@lseelenbinder
Copy link
Member

I assume you mean the issue where updating a buffer that's currently in use will stall the GPU?

Right, either GPU stalls CPU or vice-versa.

If this turns out the be a problem we could probably go back to the technique of having 2 swapping buffers so we can update a copy that isn't currently in use.

Definitely.

This whole discussion is primarily about changes due to setFeatureState on a specific feature.
We use this to mark specific features on hover, similar to this mapbox sample: https://docs.mapbox.com/mapbox-gl-js/example/hover-styles/

Ah, yes. That makes sense. You need changes to individual features (flip a bool, adjust a color) but very little by way of geometry updates (so the same vertex set but different additional data on the vertices).

I also didn't measure if there was actually any performance issue with buffer-updates at the moment.
But looking at the code, it's weird to see these full buffer updates. I've also seen many different websites with hundreds of symbols per tile, so I'd assume that updating all the buckets isn't the smartest thing to do.

In my experience, these libraries (web and native) tends to be strongly CPU bound not GPU bound, so a few extra buffer copies rarely affects the performance. If we test and see that's not the case, then cool, and this is a reasonable path to addressing it.

@JannikGM
Copy link
Contributor Author

JannikGM commented Mar 22, 2021

Right, either GPU stalls CPU or vice-versa.

I don't think I've ever seen a blocking buffer update.
I definitely saw GPUs stalling on a buffer update, but not in the past 10 years or so.
Most drivers should be smart enough to mirror your buffer.

In my experience, these libraries (web and native) tends to be strongly CPU bound not GPU bound, so a few extra buffer copies rarely affects the performance. If we test and see that's not the case, then cool, and this is a reasonable path to addressing it.

This is precisely why I suspect that buffer updates could be slow: we are CPU bound, and buffer updates can be bad on CPU.

Traditionally, larger buffer updates are at risk of being CPU intense as the driver might have to rearrange or compress data. Small buffer updates, can even be injected into the GPU command lists by some drivers, so their overhead can be much smaller.

I suspect that the Browser → Sandbox IPC adds some CPU overhead for sending large amounts of data around, too.

Also, I didn't check yet, but I assume mapbox will also walk over all features and recreate the typed-arrays for them, so I expect additional CPU overhead in that. Therefore, delta-updates should probably implemented at that level (somewhere near setFeatureState; far above the WebGL buffer abstraction).
(Edit: Upstream issue mapbox/mapbox-gl-js#6020 via mapbox/mapbox-gl-js#6255 which is mentioned in the code)
(Edit: Looks like FeatueStates already get a bit of diff'ing)
(Edit: Should be enough to use a dirty-bitmap to keep track of start and end here, so that the upload is skipped in the upload)

@lseelenbinder
Copy link
Member

Thanks for digging in to this further! Using a dirty-bitmap or equivalent sounds logical when only feature state is changing, since that's a 1:1 update of individual feature values.

This is precisely why I suspect that buffer updates could be slow: we are CPU bound, and buffer updates can be bad on CPU.

This makes sense, especially adding in the complexity of Browser / Sandboxing and the significant amount of data maps have to update for every frame, depending on the scene.

@github-actions
Copy link
Contributor

This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days.

@github-actions github-actions bot added the Stale label Oct 23, 2021
@github-actions
Copy link
Contributor

This issue was closed because it has been stalled for 7 days with no activity.

@JannikGM
Copy link
Contributor Author

I think it might still be worth looking into this. Reopened

@JannikGM JannikGM reopened this Nov 22, 2021
@github-actions github-actions bot removed the Stale label Nov 23, 2021
@github-actions
Copy link
Contributor

This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 30 days.

@github-actions github-actions bot added the Stale label May 23, 2022
@github-actions
Copy link
Contributor

This issue was closed because it has been stalled for 30 days with no activity.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants