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"
12 
13 namespace impeller {
14 namespace testing {
15 
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 
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 
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