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
Redesign WebGL backend using ReGL #10861
Redesign WebGL backend using ReGL #10861
Conversation
Am I on the right track here? It would be nice to receive some feedback before I continue with it. |
@ianthomas23, we are currently finalizing a release, so this will have to wait until we're done. In any case, this is definitively a good start. In the meantime I would add extensive visuals tests (different sizes, joins, patterns, overlap, etc.) (including comparing to canvas; though this doesn't imply it has to match perfectly) and fix the |
I think this what we care most about in this case. Thick lines are pretty rare. Also if we decide that webgl is not a drop-in replacement for canvas, then there may not be an issue altogether. |
@ianthomas23 sorry for the delay, as @mattpap mentioned we mostly need to get though a 2.3 release and then we can put more attention in to other waiting work. One little suggestion I do have off the bat is to rename |
@ianthomas23, you need to rebase this on top of |
Rebased. I was planning to fix the dashed lines before I add new tests and check the existing ones. |
Dash offsets and joins with butt end caps are done: It is getting hard to tell the difference between canvas and webgl here. I need to tweak the antialiasing at the joins a little, and joins with round or square end caps are not good enough yet. I intend to write the tests and look at markers before improving dashes further. I need a break from dashes 😁 |
@ianthomas23 this is looking great! We are finally at a place to cut a release candidate in the next day or so and release early next week so I very much look forward to being able to move on this more directly on |
@ianthomas23 what are your preferences here: would you like to see instanced lines work merged earlier, or do you want to try to have a single PR that handles lines and markers w/ ReGL at once? Now that 2.3 is out I definitely want to help you move this forward as fast as you can accommodate. Edit: I spoke too soon, looks like marker work was already added? Let us know what help/support you can best use at this point. Very excited about this! |
@bryevdv Yes, the markers use regl now too. I hadn't intended to do this yet, but it turned out to be easier than trying to get lines and markers working with different webgl initialisation. Functionally, the PR is > 90% there. The biggest thing left to do is update the existing tests and add comprehensive new ones. I've been working on these this evening, but then also decided to rebase to branch-2.4 and am stuck in a hole of git conflicts that I am dealing with slowly and carefully! There's a bunch of smaller things I need to do, but I'm confident they aren't too tricky. I will need some help on some TypeScript issues that I'm still not happy with, and I'm failing a test that I don't fully understand. Maybe we can talk about those next week after I've dealt with the other stuff. After this PR I'll need to do another one to tweak the existing markers and add all of the missing ones, and there is probably another PR to improve dashed lines with square/round end caps. After that I can move onto filled polygons, etc. Probably some of the architecture of what I've done isn't ideal, but I think the best plan is to stick with what we have until I've added more webgl and am more familiar with the rest of bokeh. Just after a release seems a good time to start making such changes. I've been watching from afar the work that you and @mattpap have been doing to get 2.3 out of the door, and I clearly underestimated the amount of work that would be. You both deserve a rest! Finally, off-topic here but I expect of interest is that I have started to work on packaging the C++ contour calculation code as a separate module. Early days yet, but you can add it to the bokeh roadmap for this year. |
bokehjs/package.json
Outdated
@@ -79,6 +79,7 @@ | |||
"@bokeh/numbro": "^1.6.2", | |||
"@bokeh/slickgrid": "~2.4.2701", | |||
"choices.js": "^9.0.1", | |||
"ci": "^1.0.0", |
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.
This seems an unnecessary dependency. If you're using this in your own workflow, you should npm install -g ci
.
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.
Yes, it's a mistake. I need to go through the package changes carefully as there are some I added that I later decided I didn't need but I may not have removed them fully.
const line_visuals = this.glyph.visuals.line | ||
|
||
const color = color2rgba(line_visuals.line_color.value, line_visuals.line_alpha.value) | ||
this._color = color.map(function(val) { return val/255 }) |
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.
(val) => val/255
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.
OK.
|
||
const cap_lookup: {[key: string]: number} = {butt: 0, round: 1, square: 2} | ||
|
||
const join_lookup: {[key: string]: number} = {miter: 0, round: 1, bevel: 2} |
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 would be better to not provide an explicit type in those two cases. You will get the precise types from type inference, which will not allow you to accidentally provide invalid cases later on.
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.
OK.
I could do with some help. I've had to rework the marker webgl typescript to deal with zooming and selection using bokeh/bokehjs/src/lib/models/glyphs/circle.ts Lines 37 to 44 in 346e694
Hence there are some not-fully initialized webgl circles which cause problems. I don't understand the 4 calls to
|
It appears that not quite yet, as "Bring 2.4 branch up to date" commit is still there. Reset your local
and then
|
@ianthomas23, besides the size issue, what else needs to be done in this PR, or is it ready at this point? |
I've added visual tests comparing canvas, svg and webgl side-by-side, e.g. Solid lines are very good, dashed lines vary (thin lines are good, thick lines with e.g. round caps are not good), and markers are no better or worse than they used to be. I have a list of 15 improvements I'd like to make from the minor (antialiasing of thin solid lines that are almost horizontal or vertical needs tweaking) to the major (some marker types missing), and a few unrelated but notable ones (svg backend does not use My preference is to try to bring this to a close and deal with those 15 issues (and whatever new ones arise) separately later. In other words, consider this a "transition to regl" PR rather than a "fix webgl for lines and markers" PR. There are 2 other issues that do need dealing with. I've partially written a canvas vs webgl comparison test with the idea of storing canvas baseline images and using CI to compare newly-generated webgl images against those canvas baselines. But this doesn't fit with the existing image comparisons bokeh/bokehjs/test/devtools/devtools.ts Lines 435 to 439 in 50b88be
which are, I think, based on number of different pixels exceeding a threshold. A better option here for canvas-webgl comparisons is to expect near-identical RGB but allow differing alpha as the differences are primarily due to antialiasing. This looks like a non-trivial addition to the testing code. Secondly, as discussed previously regl has made the minimized javascript too big. I haven't yet looked at whether it is possible to reduce this given the possibilities of a separate webgl bundle. But I don't really know what that involves. |
👍 from me |
@ianthomas23, so let's update bundle sizes to fix |
@mattpap OK, I will do that. I'll also remove the canvas vs webgl comparison that I started and put it on my "todo" list instead. Should I squash the commits? |
@ianthomas23 We normally "Squash and merge" PRs so it does not matter so much on our end. If you want a tidier commit list in the merge commit message, would be the only reason. |
public get(pattern: number[]): DashReturn { | ||
// Limit pattern to even number of items. | ||
if (pattern.length % 2 == 1) | ||
pattern = pattern.slice(0, -1) |
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.
For the sake of compatibility with 2d canvas, this should be pattern = concat(pattern, pattern)
. Though it may not happen at all, because odd patterns should be normalized at an earlier stage, thus a simple assertion would also suffice.
As long as we support SVG output, which seems to be a pretty popular feature, we can't remove any canvas related code, because it's responsible for SVG output as well. Besides this, canvas rendering related code is small compared to other code paths, like hit testing. |
The threshold is to deal with browsers' issues on test-by-test basis (see |
@ianthomas23, let's start issues for the remaining discussions/tasks/bugs. |
@mattpap Thanks for the pointers about the image testing. This sort of information is really useful as I find my way around the codebase. I'll write up an issue for the cross-backend testing. Maybe a pragmatic approach is best here of setting up some comparisons as soon as possible, even if they are crude and/or with a high tolerance, and then honing them to make them more useful in time. Although probably lower priority work than some of the other missing things. My concern is 1 pixel translation errors and suchlike, which the human eye can easily miss (well mine certainly can) so a repeatable programmatic way of checking this would be useful. |
Thank you @ianthomas23 for jumping in and taking such an involved interest in this, I am really excited for the new state and trajectory of webgl support! 🙏 |
@ianthomas23 Just FYI for the follow-on issues, the examples in the docs WebGL section have some artifacting: Edit: for easier ref these are the "10k" examples under |
Yuck, that is ugly! It looks like incorrect alpha-blending that doesn't occur on my dev system. Presumably there are slightly different defaults on different hardware/browser that I need to explicitly set. |
* Webgl lines using regl * Renamed line shader files * Improved types * Correct dash offset * Added user-specified dash offset * Dashes at joins mostly done * Webgl markers using regl * Streamline webgl transforms * Remove unnecessary caching of webgl line data * Unified webgl initialisation * Updated existing webgl test images, linux only * Updated existing webgl test images, macos and windows * eslint fixes * Fixed webgl marker ts to cope with zooming and selection * Review comments * Improve dashed lines with round/square end caps * Switch dash textures from float to uint8 to work on mobile devices * Alter missing point threshold for lower-precision devices * Correct selection and zoom of webgl circles Includes webgl backend fix for issue #9230. * Add webgl line tests (canvas, svg and webgl side-by-side). Also fixed a few bugs. * Add macos and windows test images * Increase js codebase sizes and tidy up * Increase bundle size margin some more Co-authored-by: Mateusz Paprocki <mattpap@gmail.com>
This is WIP to replace the previous webgl line code with instanced line rendering using the regl javascript library. I have rewritten both vertex and fragment shaders, and regl now does most of the webgl heavy lifting of creating vertex buffers, textures, etc. The new code is simpler, hopefully easier to understand, and there is a significant reduction in the amount of data sent from CPU to GPU which will eventually give a performance benefit.
Above example for solid lines was produced by the following code:
The output looks identical to my naked eye; there are some slight differences in antialiasing at the edge if you zoom in.
Dashed lines still need some more work: neither the start offset or user-defined offsets are correct, and joins are not correct either. But it almost acceptable for thin lines.
I've tried to keep the code architecture similar to before as it is a big enough change without also changing the architecture, and I wanted to leave the (unmodified) marker webgl code still working. But I haven't succeeded here, if you use both the old webgl markers and new webgl lines on the same canvas strange things happen presumably through sharing webgl resources that are initialised in two incompatible ways. So the webgl marker code needs to be changed in tandem with this, either in this PR or another one soon after.
My webgl initialisation is also poor, if you don't have the correct extensions it fails ungracefully. Fixing this will be easy when the markers are changed.
Things I know I need to do:
pixel_ratio
which I have ignored so far.I am interested in what others think might be problems that I haven't thought of, e.g. multiple renderings of the same data, interactive changes. Also my typescript isn't very good yet, I am learning it quickly but I am at the stage of it being both really useful and really annoying compared to pure javascript, so I am expecting to have to make changes here.
If anyone wants to compile and play with the code, there are a couple of variables in
webgl/line_gl.ts
that are interesting to change: settingdebug_show_mesh
on line 52 totrue
will render the webgl mesh on top of the lines, andantialiasing
on line 49 can be altered to vary the width of the antialiasing.