-
Notifications
You must be signed in to change notification settings - Fork 2.3k
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
Render raster loop #3399
Render raster loop #3399
Conversation
Please fix the build (linting errors) for the last commit. |
Still failing a test. Also, you should probably rebase the branch to fresh master (after it switched to ES6 features like let/const #3388) |
e9dc713
to
78e6c51
Compare
okay! I rebased from master. does this look good now? |
@@ -68,7 +77,6 @@ exports.getImage = function(url, callback) { | |||
context.drawImage(img, 0, 0); | |||
return context.getImageData(0, 0, img.width, img.height).data; | |||
}; | |||
return img; |
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.
It looks like these code changes originate in #3302. Can you remove that code from this PR and keep the two independent?
parentTile = this.findLoadedParent(coord, minCoveringZoom, parentsForFading); | ||
if (parentTile) { | ||
this.addTile(parentTile.coord); | ||
} |
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.
Why did you remove this.addTile
from findLoadedParent
and then add it to all the call sites of findLoadedParent
?
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.
findLoadedParent()
is also called from within draw_raster.js
. It was important not to call addTile
again from there to avoid the the render loop. We could have fixed this another way but this seemed to make the most sense given the name findLoadedParent()
I wouldn't have expected it to retain a tile.
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.
Got it. This makes sense 👍
@@ -722,7 +722,6 @@ test('SourceCache#findLoadedParent', (t) => { | |||
t.equal(sourceCache.findLoadedParent(new TileCoord(2, 0, 0), 0, retain), tile); | |||
t.deepEqual(retain, expectedRetain); | |||
t.equal(sourceCache._cache.order.length, 0); | |||
t.equal(sourceCache._tiles[tile.coord.id], tile); | |||
|
|||
t.end(); | |||
}); |
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.
Can you add a test that triggers the render raster loop to ensure this behavior does not regress?
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 can try
This is looking good @vicapow! Just two items to hit before we can 🚢 this: Launch Checklist
|
@vicapow any updates? |
@mourner I've spent a bit of time trying to write a test for this but got stuck trying to replicate the issue in the testing environment and haven't had time to dig into it more. |
Specifically, I get the following error. Maybe this is related to the tests running from Node.JS instead of the browser? Error: Uncaught [TypeError: texImage2D(GLenum, GLint, GLenum, GLint, GLenum, GLenum, ImageData)]
at reportException (/Users/victorpowell/Documents/projects/mapbox-gl-js/node_modules/jsdom/lib/jsdom/living/helpers/runtime-script-errors.js:58:24)
at invokeEventListeners (/Users/victorpowell/Documents/projects/mapbox-gl-js/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:235:9)
at invokeInlineListeners (/Users/victorpowell/Documents/projects/mapbox-gl-js/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:166:7)
at HTMLImageElementImpl._dispatch (/Users/victorpowell/Documents/projects/mapbox-gl-js/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:122:7)
at HTMLImageElementImpl.dispatchEvent (/Users/victorpowell/Documents/projects/mapbox-gl-js/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:87:17)
at HTMLImageElementImpl.dispatchEvent (/Users/victorpowell/Documents/projects/mapbox-gl-js/node_modules/jsdom/lib/jsdom/living/nodes/HTMLElement-impl.js:36:27)
at e (/Users/victorpowell/Documents/projects/mapbox-gl-js/node_modules/jsdom/lib/jsdom/browser/resource-loader.js:51:15)
at Object.check (/Users/victorpowell/Documents/projects/mapbox-gl-js/node_modules/jsdom/lib/jsdom/living/nodes/Document-impl.js:85:11)
at /Users/victorpowell/Documents/projects/mapbox-gl-js/node_modules/jsdom/lib/jsdom/living/nodes/Document-impl.js:104:12
at HTMLImageElementImpl._attrModified (/Users/victorpowell/Documents/projects/mapbox-gl-js/node_modules/jsdom/lib/jsdom/living/nodes/HTMLImageElement-impl.js:35:37)
at Object.exports.appendAttribute (/Users/victorpowell/Documents/projects/mapbox-gl-js/node_modules/jsdom/lib/jsdom/living/attributes.js:204:11)
at HTMLImageElementImpl.setAttribute (/Users/victorpowell/Documents/projects/mapbox-gl-js/node_modules/jsdom/lib/jsdom/living/nodes/Element-impl.js:329:18)
at HTMLImageElementImpl.set src [as src] (/Users/victorpowell/Documents/projects/mapbox-gl-js/node_modules/jsdom/lib/jsdom/living/nodes/HTMLImageElement-impl.js:51:10)
at HTMLImageElement.set (/Users/victorpowell/Documents/projects/mapbox-gl-js/node_modules/jsdom/lib/jsdom/living/generated/HTMLImageElement.js:40:20)
at exports.getArrayBuffer (/Users/victorpowell/Documents/projects/mapbox-gl-js/js/util/ajax.js:70:21)
at FakeXMLHttpRequest.xhr.onload (/Users/victorpowell/Documents/projects/mapbox-gl-js/js/util/ajax.js:41:13) TypeError: texImage2D(GLenum, GLint, GLenum, GLint, GLenum, GLenum, ImageData)
at WebGLRenderingContext.texImage2D (/Users/victorpowell/Documents/projects/mapbox-gl-js/node_modules/gl/webgl.js:3499:13)
at RasterTileSource.done (/Users/victorpowell/Documents/projects/mapbox-gl-js/js/source/raster_tile_source.js:80:20)
at HTMLImageElement.img.onload (/Users/victorpowell/Documents/projects/mapbox-gl-js/js/util/ajax.js:63:13)
at HTMLImageElement.callback.(anonymous function) (/Users/victorpowell/Documents/projects/mapbox-gl-js/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:289:32)
at invokeEventListeners (/Users/victorpowell/Documents/projects/mapbox-gl-js/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:219:27)
at invokeInlineListeners (/Users/victorpowell/Documents/projects/mapbox-gl-js/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:166:7)
at HTMLImageElementImpl._dispatch (/Users/victorpowell/Documents/projects/mapbox-gl-js/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:122:7)
at HTMLImageElementImpl.dispatchEvent (/Users/victorpowell/Documents/projects/mapbox-gl-js/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:87:17)
at HTMLImageElementImpl.dispatchEvent (/Users/victorpowell/Documents/projects/mapbox-gl-js/node_modules/jsdom/lib/jsdom/living/nodes/HTMLElement-impl.js:36:27)
at e (/Users/victorpowell/Documents/projects/mapbox-gl-js/node_modules/jsdom/lib/jsdom/browser/resource-loader.js:51:15)
at Object.check (/Users/victorpowell/Documents/projects/mapbox-gl-js/node_modules/jsdom/lib/jsdom/living/nodes/Document-impl.js:85:11)
at /Users/victorpowell/Documents/projects/mapbox-gl-js/node_modules/jsdom/lib/jsdom/living/nodes/Document-impl.js:104:12
at HTMLImageElementImpl._attrModified (/Users/victorpowell/Documents/projects/mapbox-gl-js/node_modules/jsdom/lib/jsdom/living/nodes/HTMLImageElement-impl.js:35:37)
at Object.exports.appendAttribute (/Users/victorpowell/Documents/projects/mapbox-gl-js/node_modules/jsdom/lib/jsdom/living/attributes.js:204:11)
at HTMLImageElementImpl.setAttribute (/Users/victorpowell/Documents/projects/mapbox-gl-js/node_modules/jsdom/lib/jsdom/living/nodes/Element-impl.js:329:18)
at HTMLImageElementImpl.set src [as src] (/Users/victorpowell/Documents/projects/mapbox-gl-js/node_modules/jsdom/lib/jsdom/living/nodes/HTMLImageElement-impl.js:51:10) If it helps, this is what I have so far. t.test('#loaded() stabilizes with raster tile zooming', t => {
window.server.respondWith(request => {
request.respond(204, {'Content-Type': 'image/png'}, '');
});
window.server.autoRespond = true;
window.server.autoRespondAfter = 10;
const style = createStyle();
const sourceName = 'example-raster-source';
style.sources[sourceName] = {
type: 'raster',
tileSize: 256,
scheme: 'xyz',
tilejson: '2.0.0',
tiles: ['http://example.com/{z}/{x}/{y}.png']
};
style.layers.push({
id: `${sourceName}-layer`,
type: 'raster',
source: sourceName,
'source-layer': 'raster_full',
paint: {
'raster-opacity': 1
}
});
console.log('create map');
const map = createMap({style, zoom: 15, center: [-77.0186, 38.8888]});
map.on('load', () => {
console.log('map loaded');
console.log(map.loaded());
map.jumpTo({zoom: 14});
setTimeout(() => {
map.jumpTo({zoom: 16});
setTimeout(() => {
let renderCount = 0;
map.on('render', () => {
// should only be called once.
t.end();
// for debugging the tests...
renderCount++;
console.log(renderCount);
});
}, 10);
}, 10);
});
}); |
Any recommendation on the issues I'm running into with writing tests for this fix? |
has this issue been resolved? I noticed that in release 0.27 #3302 had been resolved. does that fix this problem? My CPU is still blowing up when I zoom around on raster tiles. |
Until it's resolved, is there any quick workaround to cancel a render? Something like: let dirty = false;
map.on('movestart', function(e) {
dirty = true;
});
map.on('moveend', function(e) {
dirty = false;
});
map.on('render', function(e) {
if(!dirty) e.target.cancelRender();
}); Thanks. |
78e6c51
to
edee34a
Compare
What's the status of this/what's left to do to? I've manually tested this change before/after and it fixes the loop/high CPU on raster sources. |
@andrewharvey We're trying to get a regression test in place for this bug before merging this PR. @mollymerp is working on that today. |
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 spent a day trying to figure out how to fake the rendering loop but sinon and jsdom have limitations such that writing a test for this is not straightforward. in the interest of getting this fix 🚢 for users who are blocked by this, lets merge and I'll open a ticket to investigate alternative testing methods and/or refactoring of SourceCache
entirely.
per chat -- shipping now for expediency. will re-investigate testing at a later date
Thanks again for tracking this down @vicapow ! |
Fixes: #3398
Tested this using a modified "debug" page.
The issue is somewhat complex but here's a pseudo code description of the looping behavior:
To break out of this loop, I avoid adding the tile back inside of
drawRasterTile()