Skip to content
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

Add culling #8089

Merged
merged 20 commits into from
Feb 22, 2022
Merged

Add culling #8089

merged 20 commits into from
Feb 22, 2022

Conversation

dev7355608
Copy link
Collaborator

@dev7355608 dev7355608 commented Jan 6, 2022

Description of change

I propose to add culling to Container.render(Advanced). I know there are @pixi-essentials/cull and pixi-cull, but they fail to take into account filter padding as far as I know: an object with a filter that has a large padding is hidden too early (filter padding is not included in the bounds of the object). This implementation of culling does not have this problem. It is also quite simple. Culling is only done if container.cullable is true.

Pre-Merge Checklist
  • Tests and/or benchmarks are included
  • Documentation is changed or added
  • Lint process passed (npm run lint)
  • Tests passed (npm run test)

@bigtimebuddy
Copy link
Member

I like this addition. It's simple and doesn't require other dependencies.

But it needs tests, particularly it would be useful for covering the use-case you described with filters.

@bigtimebuddy bigtimebuddy added this to the v6.3.0 milestone Jan 6, 2022
@dev7355608
Copy link
Collaborator Author

While I was working on the tests I noticed that my initial implementation wasn't doing what I promised (that it works correctly with filters always). I never noticed because in my own use case I only ever added culling to leaf nodes. On leaf nodes it does work with filters, but not if the cullable container has a child with a padded filter. We cannot skip the children even if the bounds do not intersect the source frame because we do not know if there's a child with a padded filter. That I fixed in the last commit.

Other changes: I added the cullable property to DisplayObject instead of Container, and I added the protected function _renderWithCulling to Container.

@dev7355608
Copy link
Collaborator Author

dev7355608 commented Jan 6, 2022

I added a few tests. I probably didn't cover every case.

Filtered containers with autoFit false that are completely of out frame cannot be culled at the moment. They're going to be culled though when #8091 is merged.

@bigtimebuddy
Copy link
Member

bigtimebuddy commented Jan 10, 2022

@GoodBoyDigital and I had a chat about this. Our biggest concern was understanding how meaningful an optimization this is. Can you show a performance test with a deeply-nested and flat scenes with many objects (1-100K)? Where does cullable breakdown? What types of gains does it have (% faster or slower)? Under what circumstances would a user consider cullable instead of doing their own or using one of the plugins you mentioned?

@dev7355608
Copy link
Collaborator Author

Playground: https://www.pixiplayground.com/#/edit/6YshCmTQnz1q35pGum1c0 (Use the dev tools FPS meter)

Deeply-nested vs flat should be more or less the same in this implementation (we cannot skip the children because of potential padded filters).

This implementation doesn't have a problem with padded filters, and the user doesn't have to do anything more than set cullable to true. With the plugins the culling system needs to be run (manually) before rendering with the correct bounds of the current render target dimensions. The plugins probably have some speed advantages because they ignore the filter padding problem, but I haven't benchmarked this implementation vs the plugins yet.

Culling is always nice to have for expensive objects that are not batched. But even for batched sprites there's a point where culling makes a noticeable FPS difference.

@dev7355608
Copy link
Collaborator Author

The advantage of the plugins is that they can cull static objects efficiently, but it's the user's responsibility to update the culling system when it's necessary. But they don't have an advantage in culling dynamic objects that need to be tested every frame; here the performance of cullable and plugins should be the same (at least in the case of no filters).

I updated the playground and added options to compare with pixi-cull and pixi-essentials/cull. pixi-cull doesn't seem to calculate the bounds correctly: the objects are hidden before they leave the frame. If you set the culling method to pixi-essentials/cull and enable filters and increase the padding, you can observe the filter padding problem. The cullable method is not affected.

@bigtimebuddy
Copy link
Member

bigtimebuddy commented Jan 11, 2022

Here are some rough numbers based on the demo (2x, no filters). This was run on a 2019 macBook pro in the latest Chrome. All values here are approximate FPS from devtools. I think 2x is a good stress test because of the high fill-rate.

Sprites no-cull cullable pixi-cull @pixi-esstentials/cull cullable speedup
30K ~21.6 ~24.0 ~24.6 ~24 ~11%
40K ~18.6 ~21.0 ~19.2 ~19.8 ~13%
50K ~15.6 ~18.0 ~16.2 ~16.8 ~15%
60K ~11.4 ~15.6 ~15.0 ~13.8 ~36%
70K ~9.6 ~13.8 ~12.6 ~12.6 ~43%
80K ~9.6 ~12.6 ~12.0 ~10.8 ~31%

Few observations:

  • cullable performs marginally better (~5-10%) than plugins with this type of scene
  • speed-up improvements are solid for large scenes, for sure

@ShukantPal
Copy link
Member

This looks good glossing over the code. I'll battle test it this weekend locally.

@GoodBoyDigital
Copy link
Member

thats not a bad improvement!

@bigtimebuddy bigtimebuddy added the ✅ Ready To Merge Helpful when issues are in the queue waiting to get merged. This means the PR is completed and has t label Jan 19, 2022
@bigtimebuddy
Copy link
Member

@dev7355608, another future optimization that we could do for cullable, if you're open, is something similar to hitArea used in interaction (e.g. cullArea). This way a user could define a Rectangle to keep from computing bounds. It could be very useful for something like Spine animations which would benefit from not calculating bounds for all children.

@dev7355608 dev7355608 mentioned this pull request Jan 25, 2022
4 tasks
@bigtimebuddy
Copy link
Member

@dev7355608 could you please merge pr/8089 (cullArea) branch into this?

@bigtimebuddy bigtimebuddy merged commit ed51102 into pixijs:dev Feb 22, 2022
@bigtimebuddy
Copy link
Member

Great work @dev7355608, I think people will find this convenient and useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
✅ Ready To Merge Helpful when issues are in the queue waiting to get merged. This means the PR is completed and has t
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants