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

Commit 03ebd64

Browse files
[Impeller] add a per-frame trace event for heap usage on Vulkan. (#51246)
Part of flutter/flutter#144617 Adds MemoryBudgetUsageMB which includes the MB of VMA allocated GPU and host memory, approximately per frame. This will be recorded in the devicelab and used to track how much memory pressure we're creating. Split out from #51187 since that was reverted (and doing big changes is a bad idea anyway).
1 parent cae8735 commit 03ebd64

File tree

8 files changed

+92
-6
lines changed

8 files changed

+92
-6
lines changed

ci/licenses_golden/excluded_files

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@
168168
../../../flutter/impeller/playground
169169
../../../flutter/impeller/renderer/backend/gles/test
170170
../../../flutter/impeller/renderer/backend/metal/texture_mtl_unittests.mm
171+
../../../flutter/impeller/renderer/backend/vulkan/allocator_vk_unittests.cc
171172
../../../flutter/impeller/renderer/backend/vulkan/blit_command_vk_unittests.cc
172173
../../../flutter/impeller/renderer/backend/vulkan/command_encoder_vk_unittests.cc
173174
../../../flutter/impeller/renderer/backend/vulkan/command_pool_vk_unittests.cc

impeller/core/allocator.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ class Allocator {
4444

4545
virtual ISize GetMaxTextureSizeSupported() const = 0;
4646

47+
/// @brief Write debug memory usage information to the dart timeline in debug
48+
/// and profile modes.
49+
///
50+
/// This is only supported on the Vulkan backend.
51+
virtual void DebugTraceMemoryStatistics() const {};
52+
4753
protected:
4854
Allocator();
4955

impeller/renderer/backend/vulkan/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import("../../../tools/impeller.gni")
88
impeller_component("vulkan_unittests") {
99
testonly = true
1010
sources = [
11+
"allocator_vk_unittests.cc",
1112
"blit_command_vk_unittests.cc",
1213
"command_encoder_vk_unittests.cc",
1314
"command_pool_vk_unittests.cc",

impeller/renderer/backend/vulkan/allocator_vk.cc

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ AllocatorVK::AllocatorVK(std::weak_ptr<Context> context,
101101
auto limits = physical_device.getProperties().limits;
102102
max_texture_size_.width = max_texture_size_.height =
103103
limits.maxImageDimension2D;
104+
physical_device.getMemoryProperties(&memory_properties_);
104105

105106
VmaVulkanFunctions proc_table = {};
106107

@@ -496,4 +497,26 @@ std::shared_ptr<DeviceBuffer> AllocatorVK::OnCreateBuffer(
496497
);
497498
}
498499

500+
size_t AllocatorVK::DebugGetHeapUsage() const {
501+
auto count = memory_properties_.memoryHeapCount;
502+
std::vector<VmaBudget> budgets(count);
503+
vmaGetHeapBudgets(allocator_.get(), budgets.data());
504+
size_t total_usage = 0;
505+
for (auto i = 0u; i < count; i++) {
506+
const VmaBudget& budget = budgets[i];
507+
total_usage += budget.usage;
508+
}
509+
// Convert bytes to MB.
510+
total_usage *= 1e-6;
511+
return total_usage;
512+
}
513+
514+
void AllocatorVK::DebugTraceMemoryStatistics() const {
515+
#ifdef IMPELLER_DEBUG
516+
FML_TRACE_COUNTER("flutter", "AllocatorVK",
517+
reinterpret_cast<int64_t>(this), // Trace Counter ID
518+
"MemoryBudgetUsageMB", DebugGetHeapUsage());
519+
#endif // IMPELLER_DEBUG
520+
}
521+
499522
} // namespace impeller

impeller/renderer/backend/vulkan/allocator_vk.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ class AllocatorVK final : public Allocator {
2424
// |Allocator|
2525
~AllocatorVK() override;
2626

27+
// Visible for testing
28+
size_t DebugGetHeapUsage() const;
29+
2730
private:
2831
friend class ContextVK;
2932

@@ -36,6 +39,7 @@ class AllocatorVK final : public Allocator {
3639
bool supports_memoryless_textures_ = false;
3740
// TODO(jonahwilliams): figure out why CI can't create these buffer pools.
3841
bool created_buffer_pool_ = true;
42+
vk::PhysicalDeviceMemoryProperties memory_properties_;
3943

4044
AllocatorVK(std::weak_ptr<Context> context,
4145
uint32_t vulkan_api_version,
@@ -58,6 +62,9 @@ class AllocatorVK final : public Allocator {
5862
// |Allocator|
5963
ISize GetMaxTextureSizeSupported() const override;
6064

65+
// |Allocator|
66+
void DebugTraceMemoryStatistics() const override;
67+
6168
AllocatorVK(const AllocatorVK&) = delete;
6269

6370
AllocatorVK& operator=(const AllocatorVK&) = delete;
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#include "flutter/testing/testing.h" // IWYU pragma: keep
6+
#include "gtest/gtest.h"
7+
#include "impeller/core/device_buffer_descriptor.h"
8+
#include "impeller/core/formats.h"
9+
#include "impeller/renderer/backend/vulkan/allocator_vk.h"
10+
#include "impeller/renderer/backend/vulkan/test/mock_vulkan.h"
11+
#include "vulkan/vulkan_enums.hpp"
12+
13+
namespace impeller {
14+
namespace testing {
15+
16+
#ifdef IMPELLER_DEBUG
17+
18+
TEST(AllocatorVKTest, RecreateSwapchainWhenSizeChanges) {
19+
auto const context = MockVulkanContextBuilder().Build();
20+
auto allocator = context->GetResourceAllocator();
21+
22+
EXPECT_EQ(
23+
reinterpret_cast<AllocatorVK*>(allocator.get())->DebugGetHeapUsage(), 0u);
24+
25+
allocator->CreateBuffer(DeviceBufferDescriptor{
26+
.storage_mode = StorageMode::kDevicePrivate,
27+
.size = 1024,
28+
});
29+
30+
// Usage increases beyond the size of the allocated buffer since VMA will
31+
// first allocate large blocks of memory and then suballocate small memory
32+
// allocations.
33+
EXPECT_EQ(
34+
reinterpret_cast<AllocatorVK*>(allocator.get())->DebugGetHeapUsage(),
35+
16u);
36+
}
37+
38+
#endif // IMPELLER_DEBUG
39+
40+
} // namespace testing
41+
} // namespace impeller

impeller/renderer/backend/vulkan/surface_context_vk.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ std::unique_ptr<Surface> SurfaceContextVK::AcquireNextSurface() {
8888
.DidAcquireSurfaceFrame();
8989
}
9090
parent_->GetCommandPoolRecycler()->Dispose();
91+
parent_->GetResourceAllocator()->DebugTraceMemoryStatistics();
9192
return surface;
9293
}
9394

impeller/renderer/backend/vulkan/test/mock_vulkan.cc

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -221,14 +221,20 @@ VkResult vkCreateInstance(const VkInstanceCreateInfo* pCreateInfo,
221221
void vkGetPhysicalDeviceMemoryProperties(
222222
VkPhysicalDevice physicalDevice,
223223
VkPhysicalDeviceMemoryProperties* pMemoryProperties) {
224-
pMemoryProperties->memoryTypeCount = 1;
224+
pMemoryProperties->memoryTypeCount = 2;
225+
pMemoryProperties->memoryHeapCount = 2;
225226
pMemoryProperties->memoryTypes[0].heapIndex = 0;
226-
// pMemoryProperties->memoryTypes[0].propertyFlags =
227-
// VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
228-
// VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD;
229-
pMemoryProperties->memoryHeapCount = 1;
227+
pMemoryProperties->memoryTypes[0].propertyFlags =
228+
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
229+
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
230+
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
231+
pMemoryProperties->memoryTypes[1].heapIndex = 1;
232+
pMemoryProperties->memoryTypes[1].propertyFlags =
233+
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
230234
pMemoryProperties->memoryHeaps[0].size = 1024 * 1024 * 1024;
231-
pMemoryProperties->memoryHeaps[0].flags = 0;
235+
pMemoryProperties->memoryHeaps[0].flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT;
236+
pMemoryProperties->memoryHeaps[1].size = 1024 * 1024 * 1024;
237+
pMemoryProperties->memoryHeaps[1].flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT;
232238
}
233239

234240
VkResult vkCreatePipelineCache(VkDevice device,

0 commit comments

Comments
 (0)