-
-
Notifications
You must be signed in to change notification settings - Fork 910
fix: contextRestored event not working #6398
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
base: main
Are you sure you want to change the base?
fix: contextRestored event not working #6398
Conversation
Thanks for taking the time to open this PR! |
b6e716c
to
509e68e
Compare
Thanks for your response.
Regarding the naming convention for destruction methods, I noticed that several classes already use destroy, so it seemed consistent to follow the same pattern. For clearing everything, I tested that the “polygons” and “custom” layers render correctly again afterward. Specifically, I copy the Style when the context lost event occurs, then recreate it on context restore. My thinking was that destroying everything first and then rebuilding it would help avoid memory leaks. However, I’m not completely sure if I’m destroying everything properly. Finally, do you think I should add more tests, such as rendering tests, to verify that the map looks identical after the restore? |
I added a commit introducing an operation called loseAndRestoreContext for test-render. |
I don't see an added value in adding this to the render tests... Render test are more static in most cases, they also should be paired to native, which I'm not sure context loss exists there... |
Render tests compare the rendered output as image data against the expected image data. They use Puppeteer, which runs a real headless browser (usually Chromium or Chrome). This allows the tests to use WebGL in the browser to render layers, styles, etc. Since this PR destroys and recreates the Style, I added an operation to check some render tests. Right now, I’m running it locally with all the style.json (I added LoseAndRestoreContext operation to them). Most tests are passing, but a few specific ones are timing out. I’m investigating the cause and working on fixing it. |
I was just asking whether you want me to add the LoseAndRestoreContext operation to all existing tests, since it could slow them down. |
In my opinion, if all render tests pass with the LoseAndRestoreContext operation enabled, the PR can be considered fully safe. |
add3bad
to
68f8044
Compare
As a feature test, that's a great tests, but I don't want to run this on every PR, the integration test you added is good enough for keeping the functionality working for the long run... |
So I’ll remove the last commit with the LoseAndRestoreContext operation in the render tests? |
Yes please |
e752487
to
953b44a
Compare
I fixed an issue where images added via map.addImage were not being restored after a context restore. Also, I should mention that custom layers need to be re-added after a context restore. In test/examples/add-a-3d-model-to-globe-using-threejs.html, this works well because the example adds the custom layer inside map.on('style.load', ...), so it automatically gets added again when the context is restored. |
1a117a8
to
9f7f5ab
Compare
BTW, what about customer layers? I don't think they withstand context lost, do they? |
They need to be restored either from the contextrestore event fired by the map or by listening to the style.load event, which is triggered when the style is restored. |
|
||
// Remove event listeners | ||
this.setEventedParent(null); | ||
this.dispatcher.remove(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about unregistering to events from workers? Also what about cleaning workers data etc?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’m not very familiar with this part of the code yet; I need to study it more to fully understand what you’re suggesting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Were you thinking about something like this ?
// Clear workers
this.dispatcher.workerPool.release(this.map._mapId);
this.dispatcher.actors.forEach((actor) => {
actor.remove();
});
this.dispatcher.workerPool.workers.forEach((worker) => {
worker.terminate();
});
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The dispatcher is registering events in style.ts file:
maplibre-gl-js/src/style/style.ts
Line 246 in 5e0f8f7
this.dispatcher.registerMessageHandler(MessageType.getGlyphs, (mapId, params) => { |
I'm guessing these need to be unregistered to avoid receiving messages for a destroyed style.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Regarding workers, these are created when the app starts, but I'm not sure how stateless they are, so I would recommend looking at what is stored in worker.ts file and see if clean up is needed there as well:
https://github.com/maplibre/maplibre-gl-js/blob/main/src/source/worker.ts
I've added a few comments. |
ead05d6
to
903c34b
Compare
Style should be cleared properly on contextLost event to ensure contextRestored event works as expected. contextRestored should create a new Style object from the existing one.
903c34b
to
47aea35
Compare
this._serializedLayers = {}; | ||
|
||
// Reset other internal state | ||
this.stylesheet = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider moving all this initialization logic to a method and maybe use the same method in the constructor.
centerClampedToGround: true | ||
}; | ||
|
||
let oldContextStyle: { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should define a global variable... I'm guessing that this won't work when there are multiple maps in the same page...
If we this is not handled automatically at least a In what scenario this happens that all this code is needed? I'm a bit lost around the motivation of this PR, that slowly becomes bigger and bigger... |
Launch Checklist
CHANGELOG.md
under the## main
section.Problem description:
The map is not properly restored after a contextRestored event. Some buffers and resources from the previous context are still being used, which causes the new context to crash and triggers WebGL warnings.
Changes:
Ensure that the style is properly cleared when a contextLost event occurs, so that the contextRestored event can work as expected.
On contextRestored, create a new Style object based on the existing one to fully reinitialize the style state.
Pull request note:
I'm not entirely confident about all the changes in this PR, as this area is new to me. A review with advice and suggestions would be greatly appreciated.
I also need help with testing, since it requires a real WebGL API. Could you provide some guidance or share a sample test setup?
Related issue :
#6242