| Flutter Impeller |

blit_pass_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 <cstdint>
6 #include "flutter/display_list/dl_builder.h"
7 #include "flutter/impeller/display_list/aiks_unittests.h"
8 #include "flutter/impeller/display_list/dl_image_impeller.h"
9 #include "fml/mapping.h"
10 #include "gtest/gtest.h"
11 #include "impeller/base/validation.h"
12 #include "impeller/core/device_buffer.h"
13 #include "impeller/core/device_buffer_descriptor.h"
14 #include "impeller/core/formats.h"
15 #include "impeller/core/texture_descriptor.h"
16 #include "impeller/playground/playground_test.h"
17 #include "impeller/renderer/command_buffer.h"
18
19 namespace impeller {
20 namespace testing {
21
22 using flutter::DisplayListBuilder;
23 using flutter::DlColor;
24 using flutter::DlImageSampling;
25 using flutter::DlPaint;
26
27 using BlitPassTest = AiksTest;
28 INSTANTIATE_PLAYGROUND_SUITE(BlitPassTest);
29
30 TEST_P(BlitPassTest, BlitAcrossDifferentPixelFormatsFails) {
31 ScopedValidationDisable scope; // avoid noise in output.
32 auto context = GetContext();
33 auto cmd_buffer = context->CreateCommandBuffer();
34 auto blit_pass = cmd_buffer->CreateBlitPass();
35
36 TextureDescriptor src_desc;
37 src_desc.format = PixelFormat::kA8UNormInt;
38 src_desc.size = {100, 100};
39 src_desc.storage_mode = StorageMode::kHostVisible;
40 auto src = context->GetResourceAllocator()->CreateTexture(src_desc);
41
42 TextureDescriptor dst_format;
43 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
44 dst_format.size = {100, 100};
45 dst_format.storage_mode = StorageMode::kHostVisible;
46 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
47
48 EXPECT_FALSE(blit_pass->AddCopy(src, dst));
49 }
50
51 TEST_P(BlitPassTest, BlitAcrossDifferentSampleCountsFails) {
52 ScopedValidationDisable scope; // avoid noise in output.
53 auto context = GetContext();
54 auto cmd_buffer = context->CreateCommandBuffer();
55 auto blit_pass = cmd_buffer->CreateBlitPass();
56
57 TextureDescriptor src_desc;
58 src_desc.format = PixelFormat::kR8G8B8A8UNormInt;
59 src_desc.sample_count = SampleCount::kCount4;
60 src_desc.size = {100, 100};
61 auto src = context->GetResourceAllocator()->CreateTexture(src_desc);
62
63 TextureDescriptor dst_format;
64 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
65 dst_format.size = {100, 100};
66 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
67
68 EXPECT_FALSE(blit_pass->AddCopy(src, dst));
69 }
70
71 TEST_P(BlitPassTest, BlitPassesForMatchingFormats) {
72 ScopedValidationDisable scope; // avoid noise in output.
73 auto context = GetContext();
74 auto cmd_buffer = context->CreateCommandBuffer();
75 auto blit_pass = cmd_buffer->CreateBlitPass();
76
77 TextureDescriptor src_desc;
78 src_desc.format = PixelFormat::kR8G8B8A8UNormInt;
79 src_desc.size = {100, 100};
80 src_desc.storage_mode = StorageMode::kHostVisible;
81 auto src = context->GetResourceAllocator()->CreateTexture(src_desc);
82
83 TextureDescriptor dst_format;
84 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
85 dst_format.size = {100, 100};
86 dst_format.storage_mode = StorageMode::kHostVisible;
87 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
88
89 EXPECT_TRUE(blit_pass->AddCopy(src, dst));
90 }
91
92 TEST_P(BlitPassTest, ChecksInvalidSliceParameters) {
93 ScopedValidationDisable scope; // avoid noise in output.
94 auto context = GetContext();
95 auto cmd_buffer = context->CreateCommandBuffer();
96 auto blit_pass = cmd_buffer->CreateBlitPass();
97
98 TextureDescriptor dst_format;
99 dst_format.storage_mode = StorageMode::kDevicePrivate;
100 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
101 dst_format.size = {100, 100};
102 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
103
104 DeviceBufferDescriptor src_format;
105 src_format.size = 40000;
106 src_format.storage_mode = StorageMode::kHostVisible;
107 auto src = context->GetResourceAllocator()->CreateBuffer(src_format);
108
109 ASSERT_TRUE(dst);
110 ASSERT_TRUE(src);
111
112 EXPECT_FALSE(blit_pass->AddCopy(DeviceBuffer::AsBufferView(src), dst,
113 std::nullopt, "", /*mip_level=*/0,
114 /*slice=*/25));
115 EXPECT_FALSE(blit_pass->AddCopy(DeviceBuffer::AsBufferView(src), dst,
116 std::nullopt, "", /*mip_level=*/0,
117 /*slice=*/6));
118 EXPECT_TRUE(blit_pass->AddCopy(DeviceBuffer::AsBufferView(src), dst,
119 std::nullopt, "", /*mip_level=*/0,
120 /*slice=*/0));
121 }
122
123 TEST_P(BlitPassTest, CanBlitSmallRegionToUninitializedTexture) {
124 auto context = GetContext();
125 auto cmd_buffer = context->CreateCommandBuffer();
126 auto blit_pass = cmd_buffer->CreateBlitPass();
127
128 TextureDescriptor dst_format;
129 dst_format.storage_mode = StorageMode::kDevicePrivate;
130 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
131 dst_format.size = {1000, 1000};
132 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
133
134 DeviceBufferDescriptor src_format;
135 src_format.size = 4;
136 src_format.storage_mode = StorageMode::kHostVisible;
137 auto src = context->GetResourceAllocator()->CreateBuffer(src_format);
138
139 ASSERT_TRUE(dst);
140
141 EXPECT_TRUE(blit_pass->AddCopy(DeviceBuffer::AsBufferView(src), dst,
142 IRect::MakeLTRB(0, 0, 1, 1), "",
143 /*mip_level=*/0, /*slice=*/0));
144 EXPECT_TRUE(blit_pass->EncodeCommands());
145 EXPECT_TRUE(context->GetCommandQueue()->Submit({std::move(cmd_buffer)}).ok());
146 }
147
148 TEST_P(BlitPassTest, ChecksInvalidMipLevelParameter) {
149 ScopedValidationDisable scope;
150 auto context = GetContext();
151 auto cmd_buffer = context->CreateCommandBuffer();
152 auto blit_pass = cmd_buffer->CreateBlitPass();
153
154 TextureDescriptor dst_format;
155 dst_format.storage_mode = StorageMode::kDevicePrivate;
156 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
157 dst_format.size = {1000, 1000};
158 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
159
160 DeviceBufferDescriptor src_format;
161 src_format.size = 4;
162 src_format.storage_mode = StorageMode::kHostVisible;
163 auto src = context->GetResourceAllocator()->CreateBuffer(src_format);
164
165 ASSERT_TRUE(dst);
166
167 EXPECT_FALSE(blit_pass->AddCopy(DeviceBuffer::AsBufferView(src), dst,
168 IRect::MakeLTRB(0, 0, 1, 1), "",
169 /*mip_level=*/1, /*slice=*/0));
170
171 EXPECT_TRUE(blit_pass->AddCopy(DeviceBuffer::AsBufferView(src), dst,
172 IRect::MakeLTRB(0, 0, 1, 1), "",
173 /*mip_level=*/0, /*slice=*/0));
174 }
175
176 TEST_P(BlitPassTest, CanBlitToHigherTextureMipLevels) {
177 auto context = GetContext();
178 auto cmd_buffer = context->CreateCommandBuffer();
179 auto blit_pass = cmd_buffer->CreateBlitPass();
180
181 TextureDescriptor dst_format;
182 dst_format.storage_mode = StorageMode::kDevicePrivate;
183 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
184 dst_format.size = {1000, 1000};
185 dst_format.mip_count = 4;
186 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
187
188 DeviceBufferDescriptor src_format;
189 src_format.size = 4;
190 src_format.storage_mode = StorageMode::kHostVisible;
191 auto src = context->GetResourceAllocator()->CreateBuffer(src_format);
192
193 ASSERT_TRUE(dst);
194
195 EXPECT_TRUE(blit_pass->AddCopy(DeviceBuffer::AsBufferView(src), dst,
196 IRect::MakeLTRB(0, 0, 1, 1), "",
197 /*mip_level=*/1, /*slice=*/0));
198 EXPECT_TRUE(blit_pass->EncodeCommands());
199 EXPECT_TRUE(context->GetCommandQueue()->Submit({std::move(cmd_buffer)}).ok());
200 }
201
202 TEST_P(BlitPassTest, CanResizeTextures) {
203 auto context = GetContext();
204 auto cmd_buffer = context->CreateCommandBuffer();
205 auto blit_pass = cmd_buffer->CreateBlitPass();
206
207 TextureDescriptor dst_format;
208 dst_format.storage_mode = StorageMode::kDevicePrivate;
209 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
210 dst_format.size = {10, 10};
211 dst_format.usage = TextureUsage::kShaderRead | TextureUsage::kShaderWrite;
212 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
213
214 TextureDescriptor src_format;
215 src_format.storage_mode = StorageMode::kDevicePrivate;
216 src_format.format = PixelFormat::kR8G8B8A8UNormInt;
217 src_format.size = {100, 100};
218 auto src = context->GetResourceAllocator()->CreateTexture(src_format);
219
220 std::vector<uint8_t> bytes(src_format.GetByteSizeOfBaseMipLevel());
221 for (auto i = 0u; i < src_format.GetByteSizeOfBaseMipLevel(); i += 4) {
222 // RGBA
223 bytes[i + 0] = 255;
224 bytes[i + 1] = 0;
225 bytes[i + 2] = 0;
226 bytes[i + 3] = 255;
227 }
228 auto mapping = fml::DataMapping(bytes);
229 auto staging = context->GetResourceAllocator()->CreateBufferWithCopy(mapping);
230
231 ASSERT_TRUE(dst);
232 ASSERT_TRUE(src);
233 ASSERT_TRUE(staging);
234
235 EXPECT_TRUE(blit_pass->AddCopy(DeviceBuffer::AsBufferView(staging), src));
236 EXPECT_TRUE(blit_pass->ResizeTexture(src, dst));
237 EXPECT_TRUE(blit_pass->EncodeCommands());
238 EXPECT_TRUE(context->GetCommandQueue()->Submit({std::move(cmd_buffer)}).ok());
239 }
240
241 TEST_P(BlitPassTest, CanResizeTexturesPlayground) {
242 auto context = GetContext();
243 auto cmd_buffer = context->CreateCommandBuffer();
244 auto blit_pass = cmd_buffer->CreateBlitPass();
245
246 std::shared_ptr<Texture> src = CreateTextureForFixture("kalimba.jpg");
247
248 TextureDescriptor dst_format;
249 dst_format.storage_mode = StorageMode::kDevicePrivate;
250 dst_format.format = PixelFormat::kR8G8B8A8UNormInt;
251 dst_format.size = {src->GetSize().width / 2, src->GetSize().height};
252 dst_format.usage = TextureUsage::kShaderRead | TextureUsage::kShaderWrite;
253 auto dst = context->GetResourceAllocator()->CreateTexture(dst_format);
254
255 ASSERT_TRUE(dst);
256 ASSERT_TRUE(src);
257
258 EXPECT_TRUE(blit_pass->ResizeTexture(src, dst));
259 EXPECT_TRUE(blit_pass->EncodeCommands());
260 EXPECT_TRUE(context->GetCommandQueue()->Submit({std::move(cmd_buffer)}).ok());
261
262 DisplayListBuilder builder;
263 builder.Scale(GetContentScale().x, GetContentScale().y);
264 DlPaint paint;
265 paint.setColor(DlColor::kRed());
266 auto image = DlImageImpeller::Make(dst);
267 builder.DrawImage(image, flutter::DlPoint(100.0, 100.0),
268 DlImageSampling::kNearestNeighbor, &paint);
269 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
270 }
271
272 } // namespace testing
273 } // namespace impeller
aiks_unittests.h
impeller::AiksPlayground
Definition: aiks_playground.h:16
impeller::DeviceBuffer::AsBufferView
static BufferView AsBufferView(std::shared_ptr< DeviceBuffer > buffer)
Create a buffer view of this entire buffer.
Definition: device_buffer.cc:18
impeller::DlImageImpeller::Make
static sk_sp< DlImageImpeller > Make(std::shared_ptr< Texture > texture, OwningContext owning_context=OwningContext::kIO)
Definition: dl_image_impeller.cc:23
command_buffer.h
formats.h
device_buffer.h
device_buffer_descriptor.h
x
int32_t x
Definition: dl_golden_unittests.cc:458
dl_image_impeller.h
impeller::testing::AiksTest
AiksPlayground AiksTest
Definition: aiks_unittests.h:17
impeller::testing::TEST_P
TEST_P(AiksTest, DrawAtlasNoColor)
Definition: aiks_dl_atlas_unittests.cc:59
impeller::testing::INSTANTIATE_PLAYGROUND_SUITE
INSTANTIATE_PLAYGROUND_SUITE(AiksTest)
impeller
Definition: allocation.cc:12
impeller::StorageMode::kDevicePrivate
@ kDevicePrivate
impeller::StorageMode::kHostVisible
@ kHostVisible
impeller::PixelFormat::kA8UNormInt
@ kA8UNormInt
impeller::PixelFormat::kR8G8B8A8UNormInt
@ kR8G8B8A8UNormInt
impeller::DlPoint
flutter::DlPoint DlPoint
Definition: dl_dispatcher.h:24
impeller::TextureUsage::kShaderWrite
@ kShaderWrite
impeller::TextureUsage::kShaderRead
@ kShaderRead
impeller::SampleCount::kCount4
@ kCount4
playground_test.h
impeller::DeviceBufferDescriptor
Definition: device_buffer_descriptor.h:14
impeller::DeviceBufferDescriptor::storage_mode
StorageMode storage_mode
Definition: device_buffer_descriptor.h:15
impeller::DeviceBufferDescriptor::size
size_t size
Definition: device_buffer_descriptor.h:16
impeller::ScopedValidationDisable
Definition: validation.h:56
impeller::TRect::MakeLTRB
constexpr static TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition: rect.h:129
impeller::TSize::width
Type width
Definition: size.h:28
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::TextureDescriptor::GetByteSizeOfBaseMipLevel
constexpr size_t GetByteSizeOfBaseMipLevel() const
Definition: texture_descriptor.h:48
impeller::TextureDescriptor::usage
TextureUsageMask usage
Definition: texture_descriptor.h:44
impeller::TextureDescriptor::size
ISize size
Definition: texture_descriptor.h:42
impeller::TextureDescriptor::storage_mode
StorageMode storage_mode
Definition: texture_descriptor.h:39
impeller::TextureDescriptor::sample_count
SampleCount sample_count
Definition: texture_descriptor.h:45
impeller::TextureDescriptor::mip_count
size_t mip_count
Definition: texture_descriptor.h:43
impeller::TextureDescriptor::format
PixelFormat format
Definition: texture_descriptor.h:41
texture_descriptor.h
validation.h