Conversation
This is dead code right now but a step towards data driven styling nirvana.
|
Reviewed the class, generally I think this is great. There's quite a bit of complexity introduced here but I guess we can't get away from it if we want generic data-driven styling with dynamically generated buffer layouts. What I'd love to see is an example of a heavy buffer such as I also think that to make this PR mergeable, we need to rewrite everything to use Buffer2 instead of Buffer and remove the old implementation, even if we know that this is eventually going away with the Bucket/Layer2 stuff. It seems relatively easy, and this way we won't have any code without use floating around, and will be able to catch any remaining issues. |
|
This looks great! I have the same question as @mourner about whether this is as fast as explicitly written versions. Which methods are called in the worker? which are called in the main thread? If there is a clean split it might be good to separate Buffer2 into two parts. |
I have done experiments with Chances are we will have to choose between the increased flexibility of a more-generic-but-less-performant-infrastructure or a less-generic-but-more-performant-infrastructure. My gut feeling is that there's nothing agregiously slow in the hot path (just a couple function calls and some loops) and we should be able to make this work. Also, this refatoring DRYs up our buffer generation code. This will better position us to implement more complex performance optimzations in the future.
I started this project thinking I could create one PR that implemented My feeling is that allowing dead code in an isolated branch is a reasonable price to pay for a bunch of standalone ~500 line PRs instead of one XX000 line PR.
All methods are called in the worker (except All methods except I do feel desire to split this class into two and have spent some time thinking about it. But I don't see any immediate practical benefit to doing so -- we'd end up with two small tightly-coupled classes instead of one nicely-sized class. Keeping the logic for understanding buffer layouts alongside the logic for writing to those buffers makes sense to me. |
Sure. Something like a 15% slowdown sounds perfectly fine. But let's make sure on a heavy buffer.
Instead of refactoring buckets, could we just rewrite all
We could also have those two classes alongside each other in the same file (maybe one inheriting another). It could make the separation more clear — e.g. I'm not a fan of stuff like this (in the constructor here): if (worker) {
// huge chunk of code
} else {
// something completely different
} |
That sounds like a good way to get this in the door. What do you think @jfirebaugh @ansis?
To be fair, the fork in the constructor is splitting on whether we're unpacking a serialized instance or creating a new instance. I think that we should split this class into two if/when it gets unwieldy to share all code between the worker and main thread but it looks pretty clean right now imo. We might even want to mutate the buffer in the main thread in some cases. |
e25a5e2 to
1fa273a
Compare
|
Going to recut this PR... Hold on to your 🎩 👒 |
Up until now, GL JS has used hand-coded classes to specify buffer layouts and buffer manipulation operations. This worked well pre-data-driven-styling because there were < 10 possible buffer layouts. For example, here is the
TriangleElementBufferclassPost-data-driven styling, however, the number of possible buffer layouts is practically infinite because any subset of paint properties might be included in the buffer.
The first step towards proper data driven styling was to create a more general and powerful framework for buffers (temporarily called
Buffer2) which allows buffer layouts to be specified by configuration rather than code. UsingBuffer2, We could write the sameTriangleElementBufferclass as... but in practice we wouldn't write it that way. GL JS would choose the attributes for that buffer at runtime for the best performance.
The
Buffer2class will know how to construct, write to, and read from GL buffers but have no semantic understanding of their contents.Instances of
Buffer2can be (destructively) serialized and transferred across threads.cc @tmcw @mourner @kkaefer