| Flutter Impeller |

host_buffer_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 <limits>
6 #include <utility>
7 #include "flutter/testing/testing.h"
8 #include "impeller/base/validation.h"
9 #include "impeller/core/allocator.h"
10 #include "impeller/core/host_buffer.h"
11 #include "impeller/entity/entity_playground.h"
12
13 namespace impeller {
14 namespace testing {
15
16 using HostBufferTest = EntityPlayground;
17 INSTANTIATE_PLAYGROUND_SUITE(HostBufferTest);
18
19 TEST_P(HostBufferTest, CanEmplace) {
20 struct Length2 {
21 uint8_t pad[2];
22 };
23 static_assert(sizeof(Length2) == 2u);
24
25 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
26
27 for (size_t i = 0; i < 12500; i++) {
28 auto view = buffer->Emplace(Length2{});
29 ASSERT_TRUE(view);
30 ASSERT_EQ(view.range, Range(i * sizeof(Length2), 2u));
31 }
32 }
33
34 TEST_P(HostBufferTest, CanEmplaceWithAlignment) {
35 struct Length2 {
36 uint8_t pad[2];
37 };
38 static_assert(sizeof(Length2) == 2);
39 struct alignas(16) Align16 {
40 uint8_t pad[2];
41 };
42 static_assert(alignof(Align16) == 16);
43 static_assert(sizeof(Align16) == 16);
44
45 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
46 ASSERT_TRUE(buffer);
47
48 {
49 auto view = buffer->Emplace(Length2{});
50 ASSERT_TRUE(view);
51 ASSERT_EQ(view.range, Range(0u, 2u));
52 }
53
54 {
55 auto view = buffer->Emplace(Align16{});
56 ASSERT_TRUE(view);
57 ASSERT_EQ(view.range.offset, 16u);
58 ASSERT_EQ(view.range.length, 16u);
59 }
60 {
61 auto view = buffer->Emplace(Length2{});
62 ASSERT_TRUE(view);
63 ASSERT_EQ(view.range, Range(32u, 2u));
64 }
65
66 {
67 auto view = buffer->Emplace(Align16{});
68 ASSERT_TRUE(view);
69 ASSERT_EQ(view.range.offset, 48u);
70 ASSERT_EQ(view.range.length, 16u);
71 }
72 }
73
74 TEST_P(HostBufferTest, HostBufferInitialState) {
75 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
76
77 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u);
78 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
79 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 1u);
80 }
81
82 TEST_P(HostBufferTest, ResetIncrementsFrameCounter) {
83 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
84
85 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
86
87 buffer->Reset();
88 EXPECT_EQ(buffer->GetStateForTest().current_frame, 1u);
89
90 buffer->Reset();
91 EXPECT_EQ(buffer->GetStateForTest().current_frame, 2u);
92
93 buffer->Reset();
94 EXPECT_EQ(buffer->GetStateForTest().current_frame, 3u);
95
96 buffer->Reset();
97 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
98 }
99
100 TEST_P(HostBufferTest,
101 EmplacingLargerThanBlockSizeCreatesOneOffBufferCallback) {
102 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
103
104 // Emplace an amount larger than the block size, to verify that the host
105 // buffer does not create a buffer.
106 auto buffer_view = buffer->Emplace(1024000 + 10, 0, [](uint8_t* data) {});
107
108 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u);
109 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
110 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 1u);
111 }
112
113 TEST_P(HostBufferTest, EmplacingLargerThanBlockSizeCreatesOneOffBuffer) {
114 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
115
116 // Emplace an amount larger than the block size, to verify that the host
117 // buffer does not create a buffer.
118 auto buffer_view = buffer->Emplace(nullptr, 1024000 + 10, 0);
119
120 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u);
121 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
122 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 1u);
123 }
124
125 TEST_P(HostBufferTest, UnusedBuffersAreDiscardedWhenResetting) {
126 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
127
128 // Emplace two large allocations to force the allocation of a second buffer.
129 auto buffer_view_a = buffer->Emplace(1020000, 0, [](uint8_t* data) {});
130 auto buffer_view_b = buffer->Emplace(1020000, 0, [](uint8_t* data) {});
131
132 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 1u);
133 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 2u);
134 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
135
136 // Reset until we get back to this frame.
137 for (auto i = 0; i < 4; i++) {
138 buffer->Reset();
139 }
140
141 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u);
142 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 2u);
143 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
144
145 // Now when we reset, the buffer should get dropped.
146 // Reset until we get back to this frame.
147 for (auto i = 0; i < 4; i++) {
148 buffer->Reset();
149 }
150
151 EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u);
152 EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 1u);
153 EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
154 }
155
156 TEST_P(HostBufferTest, EmplaceWithProcIsAligned) {
157 auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
158
159 BufferView view = buffer->Emplace(std::array<char, 21>());
160 EXPECT_EQ(view.range, Range(0, 21));
161
162 view = buffer->Emplace(64, 16, [](uint8_t*) {});
163 EXPECT_EQ(view.range, Range(32, 64));
164 }
165
166 static constexpr const size_t kMagicFailingAllocation = 1024000 * 2;
167
168 class FailingAllocator : public Allocator {
169 public:
170 explicit FailingAllocator(std::shared_ptr<Allocator> delegate)
171 : Allocator(), delegate_(std::move(delegate)) {}
172
173 ~FailingAllocator() = default;
174
175 std::shared_ptr<DeviceBuffer> OnCreateBuffer(
176 const DeviceBufferDescriptor& desc) {
177 // Magic number used in test below to trigger failure.
178 if (desc.size == kMagicFailingAllocation) {
179 return nullptr;
180 }
181 return delegate_->CreateBuffer(desc);
182 }
183
184 std::shared_ptr<Texture> OnCreateTexture(const TextureDescriptor& desc) {
185 return delegate_->CreateTexture(desc);
186 }
187
188 ISize GetMaxTextureSizeSupported() const override {
189 return delegate_->GetMaxTextureSizeSupported();
190 }
191
192 private:
193 std::shared_ptr<Allocator> delegate_;
194 };
195
196 TEST_P(HostBufferTest, EmplaceWithFailingAllocationDoesntCrash) {
197 ScopedValidationDisable disable;
198 std::shared_ptr<FailingAllocator> allocator =
199 std::make_shared<FailingAllocator>(GetContext()->GetResourceAllocator());
200 auto buffer = HostBuffer::Create(allocator);
201
202 auto view = buffer->Emplace(nullptr, kMagicFailingAllocation, 0);
203
204 EXPECT_EQ(view.buffer, nullptr);
205 EXPECT_EQ(view.range.offset, 0u);
206 EXPECT_EQ(view.range.length, 0u);
207 }
208
209 } // namespace testing
210 } // namespace impeller
impeller::testing::kMagicFailingAllocation
static constexpr const size_t kMagicFailingAllocation
Definition: host_buffer_unittests.cc:166
host_buffer.h
impeller::DeviceBufferDescriptor
Definition: device_buffer_descriptor.h:14
data
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63
impeller::HostBuffer::Create
static std::shared_ptr< HostBuffer > Create(const std::shared_ptr< Allocator > &allocator)
Definition: host_buffer.cc:21
impeller::DeviceBufferDescriptor::size
size_t size
Definition: device_buffer_descriptor.h:16
buffer_view
BufferView buffer_view
Definition: blit_command_gles.cc:128
impeller::BufferView::range
Range range
Definition: buffer_view.h:17
validation.h
impeller::testing::INSTANTIATE_PLAYGROUND_SUITE
INSTANTIATE_PLAYGROUND_SUITE(AiksTest)
impeller::TSize
Definition: size.h:19
impeller::testing::FailingAllocator::~FailingAllocator
~FailingAllocator()=default
impeller::Allocator
An object that allocates device memory.
Definition: allocator.h:23
impeller::testing::TEST_P
TEST_P(AiksTest, DrawAtlasNoColor)
Definition: aiks_dl_atlas_unittests.cc:78
impeller::testing::FailingAllocator::OnCreateBuffer
std::shared_ptr< DeviceBuffer > OnCreateBuffer(const DeviceBufferDescriptor &desc)
Definition: host_buffer_unittests.cc:175
allocator.h
impeller::BufferView
Definition: buffer_view.h:15
impeller::EntityPlayground
Definition: entity_playground.h:16
impeller::Range
Definition: range.h:13
std
Definition: comparable.h:95
impeller::testing::FailingAllocator::GetMaxTextureSizeSupported
ISize GetMaxTextureSizeSupported() const override
Definition: host_buffer_unittests.cc:188
impeller::testing::FailingAllocator::OnCreateTexture
std::shared_ptr< Texture > OnCreateTexture(const TextureDescriptor &desc)
Definition: host_buffer_unittests.cc:184
impeller::TextureDescriptor
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...
Definition: texture_descriptor.h:38
impeller::testing::FailingAllocator::FailingAllocator
FailingAllocator(std::shared_ptr< Allocator > delegate)
Definition: host_buffer_unittests.cc:170
impeller::testing::FailingAllocator
Definition: host_buffer_unittests.cc:168
impeller::ScopedValidationDisable
Definition: validation.h:56
impeller
Definition: allocation.cc:12
entity_playground.h