Michael-F-Bryan / arcs

A Rust CAD System
https://michael-f-bryan.github.io/arcs
Apache License 2.0
253 stars 22 forks source link

draw order performance #2

Open NorthWindH opened 4 years ago

NorthWindH commented 4 years ago

Hey just read the article that was on hacker news, linked to here I think: http://adventures.michaelfbryan.com/posts/ecs-outside-of-games/

Looked at the code, looks like these lines are likely what's slowing things down: https://github.com/Michael-F-Bryan/arcs/blob/42d5a77f461dc138de17a13823f8bfbdb0bbe7ce/arcs/src/render/renderer.rs#L253-L258

And it looks like this gets used here? https://github.com/Michael-F-Bryan/arcs/blob/42d5a77f461dc138de17a13823f8bfbdb0bbe7ce/arcs/src/render/renderer.rs#L151-L168

So it looks like that calculate function has a high likelihood of running in the hot loop. Apologies for the questions, I'm not very proficient in rust.

We have some experience with this in our graphics engine (C++). A few suggestions:

That's most of what comes to mind. Hopefully it helps. Happy to chat further. Cheers!

Michael-F-Bryan commented 4 years ago

Thanks for getting in touch @NorthWindH, it's really nice to see people reading about my experiments/projects! Especially when they've done this sort of thing before.

You're 100% correct that RenderSystem::run() will be called really frequently. It's essentially the top-level render() function that'll be called whenever the drawing updates (or rather, the caller changed things and wants the canvas to be redrawn).

My "integration testing" so far has been to compile the library to WebAssembly (in debug mode :ROFL:) and hook it up to a HTML canvas, then make sure clicking on the canvas draws a dot under the cursor (it didn't... I'm guessing my maths for converting from HTML canvas coordinates with a zoomed/scaled viewport to drawing coordinates is buggy). I did pretty much the bare minimum to ensure z-order is accounted for, but I'll definitely want to use some of the tricks you mention once I start using the demo application on larger drawings.

How did you deal with situations where the viewport would change rapidly (e.g. scrolling in or out, or panning)? This is intended for a 2D CAD application so items will normally be created/removed to the world at "human" speeds, which is easy to keep up with, but when you zoom or pan it's quite easy to go from displaying 10 objects to 1000. I'm guessing under those circumstances you just need to take the cost of recomputing which items are within the viewport because there's no way out of it?

I'm also taking "render list" to be the list of items which are within the viewport and meant to be rendered, instead of something like a BSP or quad tree which is a data structure containing everything in the world organised by location, regardless of whether it would be rendered... Is that correct?

The specs crate has a feature for detecting when a component is changed (inserted, deleted, or accessed via a mutable reference) and I was thinking of leveraging that to recalculate the render list with the latest changes on every tick. We currently do something similar to automatically recalculate an object's axis-aligned bounding box... I believe it will store changes in some sort of buffered channel so the runtime cost of detecting a change should amortize to adding and removing an Id (u32 under the hood, I believe) from a ring buffer.