Flutter Impeller
allocator_vk_unittests.cc
Go to the documentation of this file.
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 <algorithm>
6 
7 #include "flutter/testing/testing.h" // IWYU pragma: keep
8 #include "gtest/gtest.h"
13 #include "impeller/core/formats.h"
16 #include "impeller/renderer/backend/vulkan/test/mock_vulkan.h"
17 #include "vulkan/vulkan_enums.hpp"
18 
19 namespace impeller {
20 namespace testing {
21 
22 TEST(AllocatorVKTest, ToVKImageUsageFlags) {
27  /*supports_memoryless_textures=*/true),
28  vk::ImageUsageFlagBits::eInputAttachment |
29  vk::ImageUsageFlagBits::eColorAttachment |
30  vk::ImageUsageFlagBits::eTransientAttachment);
31 
36  /*supports_memoryless_textures=*/true),
37  vk::ImageUsageFlagBits::eDepthStencilAttachment |
38  vk::ImageUsageFlagBits::eTransientAttachment);
39 }
40 
41 TEST(AllocatorVKTest, MemoryTypeSelectionSingleHeap) {
42  vk::PhysicalDeviceMemoryProperties properties;
43  properties.memoryTypeCount = 1;
44  properties.memoryHeapCount = 1;
45  properties.memoryTypes[0].heapIndex = 0;
46  properties.memoryTypes[0].propertyFlags =
47  vk::MemoryPropertyFlagBits::eDeviceLocal;
48  properties.memoryHeaps[0].size = 1024 * 1024 * 1024;
49  properties.memoryHeaps[0].flags = vk::MemoryHeapFlagBits::eDeviceLocal;
50 
51  EXPECT_EQ(AllocatorVK::FindMemoryTypeIndex(1, properties), 0);
52  EXPECT_EQ(AllocatorVK::FindMemoryTypeIndex(2, properties), -1);
53  EXPECT_EQ(AllocatorVK::FindMemoryTypeIndex(3, properties), 0);
54 }
55 
56 TEST(AllocatorVKTest, MemoryTypeSelectionTwoHeap) {
57  vk::PhysicalDeviceMemoryProperties properties;
58  properties.memoryTypeCount = 2;
59  properties.memoryHeapCount = 2;
60  properties.memoryTypes[0].heapIndex = 0;
61  properties.memoryTypes[0].propertyFlags =
62  vk::MemoryPropertyFlagBits::eHostVisible;
63  properties.memoryHeaps[0].size = 1024 * 1024 * 1024;
64  properties.memoryHeaps[0].flags = vk::MemoryHeapFlagBits::eDeviceLocal;
65 
66  properties.memoryTypes[1].heapIndex = 1;
67  properties.memoryTypes[1].propertyFlags =
68  vk::MemoryPropertyFlagBits::eDeviceLocal;
69  properties.memoryHeaps[1].size = 1024 * 1024 * 1024;
70  properties.memoryHeaps[1].flags = vk::MemoryHeapFlagBits::eDeviceLocal;
71 
72  // First fails because this only looks for eDeviceLocal.
73  EXPECT_EQ(AllocatorVK::FindMemoryTypeIndex(1, properties), -1);
74  EXPECT_EQ(AllocatorVK::FindMemoryTypeIndex(2, properties), 1);
75  EXPECT_EQ(AllocatorVK::FindMemoryTypeIndex(3, properties), 1);
76  EXPECT_EQ(AllocatorVK::FindMemoryTypeIndex(4, properties), -1);
77 }
78 
79 TEST(AllocatorVKTest, ImageResourceKeepsVulkanDeviceAlive) {
80  std::shared_ptr<Texture> texture;
81  std::weak_ptr<Allocator> weak_allocator;
82  {
83  auto const context = MockVulkanContextBuilder().Build();
84  weak_allocator = context->GetResourceAllocator();
85  auto allocator = context->GetResourceAllocator();
86 
87  texture = allocator->CreateTexture(TextureDescriptor{
90  .size = {1, 1},
91  });
92  context->Shutdown();
93  }
94 
95  ASSERT_TRUE(weak_allocator.lock());
96 }
97 
98 TEST(AllocatorVKTest, RetriesUncompressedOnCompressionExhausted) {
99  // Advertise fixed-rate compression support, then force the first (compressed)
100  // vkCreateImage to fail with VK_ERROR_COMPRESSION_EXHAUSTED_EXT, as the
101  // PowerVR driver does when its fixed-rate-compression resources are depleted.
102  auto const context =
103  MockVulkanContextBuilder()
104  .SetDeviceExtensions(
105  {"VK_KHR_swapchain", "VK_EXT_image_compression_control"})
106  .SetCompressionExhaustedCreateImageFailures(1)
107  .Build();
108  ASSERT_TRUE(context);
109  auto allocator = context->GetResourceAllocator();
110  ASSERT_TRUE(allocator);
111 
112  // A lossy (fixed-rate-compressed) render target. The first compressed
113  // allocation fails with COMPRESSION_EXHAUSTED; the allocator must retry
114  // without compression and still produce a valid texture instead of returning
115  // null (a null render target previously crashed the raster thread).
116  auto texture = allocator->CreateTexture(TextureDescriptor{
119  .size = {64, 64},
121  .compression_type = CompressionType::kLossy,
122  });
123 
124  ASSERT_TRUE(texture);
125  EXPECT_TRUE(texture->IsValid());
126 
127  // vkCreateImage was called twice: the compressed attempt (which failed with
128  // COMPRESSION_EXHAUSTED) and the uncompressed retry (which succeeded).
129  auto const called = GetMockVulkanFunctions(context->GetDevice());
130  EXPECT_EQ(std::count(called->begin(), called->end(), "vkCreateImage"), 2);
131 }
132 
133 #ifdef IMPELLER_DEBUG
134 
135 TEST(AllocatorVKTest, RecreateSwapchainWhenSizeChanges) {
136  auto const context = MockVulkanContextBuilder().Build();
137  auto allocator = context->GetResourceAllocator();
138 
139  EXPECT_EQ(reinterpret_cast<AllocatorVK*>(allocator.get())
141  .GetByteSize(),
142  0u);
143 
144  allocator->CreateBuffer(DeviceBufferDescriptor{
146  .size = 1024,
147  });
148 
149  // Usage increases beyond the size of the allocated buffer since VMA will
150  // first allocate large blocks of memory and then suballocate small memory
151  // allocations.
152  EXPECT_EQ(reinterpret_cast<AllocatorVK*>(allocator.get())
153  ->DebugGetHeapUsage()
154  .ConvertTo<MebiBytes>()
155  .GetSize(),
156  16u);
157 }
158 
159 #endif // IMPELLER_DEBUG
160 
161 } // namespace testing
162 } // namespace impeller
constexpr uint64_t GetByteSize() const
static int32_t FindMemoryTypeIndex(uint32_t memory_type_bits_requirement, vk::PhysicalDeviceMemoryProperties &memory_properties)
Select a matching memory type for the given [memory_type_bits_requirement], or -1 if none is found.
static vk::ImageUsageFlags ToVKImageUsageFlags(PixelFormat format, TextureUsageMask usage, StorageMode mode, bool supports_memoryless_textures)
Bytes DebugGetHeapUsage() const override
TEST(AllocationSizeTest, CanCreateTypedAllocations)
AllocationSize< 1 '024u *1 '024u > MebiBytes
std::shared_ptr< ContextGLES > context
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...