Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Conversation

@gaaclarke
Copy link
Member

@gaaclarke gaaclarke commented Jul 31, 2023

I measured the pool usage while using the wonderous app after having consolidated the pools by printing capturing the pool usage after every call of vmaCreateBuffer. The max number of allocations ever seen in this pool were 1288704 B. Each of these pools are 32 MB. So this change removes 64MB from the baseline memory usage of a Vulkan Flutter engine. Worse case for a swapchain of 3 would be roughly 3 * 1.2 MB which is well within the limits of the 32 MB buffer.

Using one pool also increases the likelihood that a buffer will have been more recently used which leads to better memory performance.

This is safe to do since buffers will only be placed back into the pool after they are disposed of.

patch used for measuring

--- a/impeller/renderer/backend/vulkan/allocator_vk.cc
+++ b/impeller/renderer/backend/vulkan/allocator_vk.cc
@@ -474,6 +474,15 @@ std::shared_ptr<DeviceBuffer> AllocatorVK::OnCreateBuffer(
                                              &buffer_allocation_info  //
                                              )};
 
+  VmaStatistics pool_stats;
+  ::vmaGetPoolStatistics(allocator_.get(), staging_buffer_pool_.get().pool,
+                         &pool_stats);
+  static uint64_t s_max = 0;
+  if (pool_stats.allocationBytes > s_max) {
+    s_max = pool_stats.allocationBytes;
+    FML_LOG(ERROR) << "pool max: " << s_max;
+  }
+
   if (result != vk::Result::eSuccess) {
     VALIDATION_LOG << "Unable to allocate a device buffer: "
                    << vk::to_string(result);

Pre-launch Checklist

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • I read the Tree Hygiene wiki page, which explains my responsibilities.
  • I read and followed the Flutter Style Guide and the C++, Objective-C, Java style guides.
  • I listed at least one issue that this PR fixes in the description above.
  • I added new tests to check the change I am making or feature I am adding, or Hixie said the PR is test-exempt. See testing the engine for instructions on writing and running engine tests.
  • I updated/added relevant documentation (doc comments with ///).
  • I signed the CLA.
  • All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel on Discord.

@flutter-dashboard
Copy link

It looks like this pull request may not have tests. Please make sure to add tests before merging. If you need an exemption to this rule, contact Hixie on the #hackers channel in Chat (don't just cc him here, he won't see it! He's on Discord!).

If you are not sure if you need tests, consider this rule of thumb: the purpose of a test is to make sure someone doesn't accidentally revert the fix. Ask yourself, is there anything in your PR that you feel it is important we not accidentally revert back to how it was before your fix?

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing.

Copy link
Contributor

@jonahwilliams jonahwilliams left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to remove the Linear allocted bit from the pool or else there is a chance to just endlessly leak memory (as allocation only happens at the end).

@jonahwilliams
Copy link
Contributor

@gaaclarke
Copy link
Member Author

You need to remove the Linear allocted bit from the pool or else there is a chance to just endlessly leak memory (as allocation only happens at the end).

Done. If we wanted to have a more optimal pool we could look into a ring buffer. Since in practice i'm seeing about 1/32 of the pool being used it's probably not hard for the algorithm to find space for new allocations.

@gaaclarke gaaclarke requested a review from jonahwilliams July 31, 2023 16:54
@jonahwilliams
Copy link
Contributor

ring buffer isn't something we can use for this, only VMA or Vulkan supported allocation strategies are reasonable.

Copy link
Contributor

@jonahwilliams jonahwilliams left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@gaaclarke gaaclarke added the autosubmit Merge PR when tree becomes green via auto submit App label Jul 31, 2023
@gaaclarke
Copy link
Member Author

ring buffer isn't something we can use for this, only VMA or Vulkan supported allocation strategies are reasonable.

The VMA documentation makes mention of using a ring buffer: https://gpuopen-librariesandsdks.github.io/VulkanMemoryAllocator/html/custom_memory_pools.html#linear_algorithm

I've read through it a few times and I'm guessing you have to implement it yourself on top of the pool? It isn't very clear.

@jonahwilliams
Copy link
Contributor

That would be a ring buffer of VMA pools, each with a linear allocated bit set. That is the current implementation, which you are removing 😄

@gaaclarke
Copy link
Member Author

That would be a ring buffer of VMA pools, each with a linear allocated bit set. That is the current implementation, which you are removing 😄

It's not that because it says the requirement is that the blockCount == 1, so it is talking about one pool acting as a ring buffer.

@jonahwilliams
Copy link
Contributor

Ahh you got me! I think that might work except, what happens if we run out of memory?

@gaaclarke
Copy link
Member Author

Ahh you got me! I think that might work except, what happens if we run out of memory?

We wouldn't in the ring buffer case because we are limited by the swapchain images we have. At worst case we would have swapchain_number of resources in memory. When the last frame is rendered all of that space will be given back to the ring. When writing overlaps reading in a ring buffer its a buffer overrun and since in practice it looks like we are using at most 1.2 MB, lets say thats per frame, we'd never get close to that point with a 32MB ring.

@jonahwilliams
Copy link
Contributor

There is no bound on the amount of memory we can use per frame. A developer could create a picture with thousands of paths that leads to many MB of geometry. Anything is possible.

@auto-submit
Copy link
Contributor

auto-submit bot commented Jul 31, 2023

auto label is removed for flutter/engine, pr: 44172, due to - The status or check suite Mac mac_clang_tidy has failed. Please fix the issues identified (or deflake) before re-applying this label.

@auto-submit auto-submit bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Jul 31, 2023
@gaaclarke gaaclarke merged commit e3f817c into flutter:main Aug 1, 2023
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Aug 1, 2023
auto-submit bot pushed a commit to flutter/flutter that referenced this pull request Aug 1, 2023
…131687)

flutter/engine@ae535c0...e3f817c

2023-08-01 [email protected] [Impeller] moved to one staging buffer pool (flutter/engine#44172)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-engine-flutter-autoroll
Please CC [email protected],[email protected],[email protected] on the revert to ensure that a human
is aware of the problem.

To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://bugs.chromium.org/p/skia/issues/entry?template=Autoroller+Bug

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
vashworth pushed a commit to vashworth/flutter that referenced this pull request Aug 2, 2023
…lutter#131687)

flutter/engine@ae535c0...e3f817c

2023-08-01 [email protected] [Impeller] moved to one staging buffer pool (flutter/engine#44172)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-engine-flutter-autoroll
Please CC [email protected],[email protected],[email protected] on the revert to ensure that a human
is aware of the problem.

To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://bugs.chromium.org/p/skia/issues/entry?template=Autoroller+Bug

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
gaaclarke added a commit to gaaclarke/engine that referenced this pull request Aug 30, 2023
I measured the pool usage while using the wonderous app after having
consolidated the pools by printing capturing the pool usage after every
call of `vmaCreateBuffer`. The max number of allocations ever seen in
this pool were 1288704 B. Each of these pools are 32 MB. So this change
removes 64MB from the baseline memory usage of a Vulkan Flutter engine.
Worse case for a swapchain of 3 would be roughly 3 * 1.2 MB which is
well within the limits of the 32 MB buffer.

Using one pool also increases the likelihood that a buffer will have
been more recently used which leads to better memory performance.

This is safe to do since buffers will only be placed back into the pool
after they are disposed of.

## patch used for measuring
```diff
--- a/impeller/renderer/backend/vulkan/allocator_vk.cc
+++ b/impeller/renderer/backend/vulkan/allocator_vk.cc
@@ -474,6 +474,15 @@ std::shared_ptr<DeviceBuffer> AllocatorVK::OnCreateBuffer(
                                              &buffer_allocation_info  //
                                              )};
 
+  VmaStatistics pool_stats;
+  ::vmaGetPoolStatistics(allocator_.get(), staging_buffer_pool_.get().pool,
+                         &pool_stats);
+  static uint64_t s_max = 0;
+  if (pool_stats.allocationBytes > s_max) {
+    s_max = pool_stats.allocationBytes;
+    FML_LOG(ERROR) << "pool max: " << s_max;
+  }
+
   if (result != vk::Result::eSuccess) {
     VALIDATION_LOG << "Unable to allocate a device buffer: "
                    << vk::to_string(result);
```

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide] and the [C++,
Objective-C, Java style guides].
- [ ] I listed at least one issue that this PR fixes in the description
above.
- [ ] I added new tests to check the change I am making or feature I am
adding, or Hixie said the PR is test-exempt. See [testing the engine]
for instructions on writing and running engine tests.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I signed the [CLA].
- [x] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#overview
[Tree Hygiene]: https://github.com/flutter/flutter/wiki/Tree-hygiene
[Flutter Style Guide]:
https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo
[C++, Objective-C, Java style guides]:
https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
[testing the engine]:
https://github.com/flutter/flutter/wiki/Testing-the-engine
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes
[Discord]: https://github.com/flutter/flutter/wiki/Chat
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

No open projects
Archived in project

Development

Successfully merging this pull request may close these issues.

2 participants