Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
content_context_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 <future>
7#include <memory>
8#include <utility>
9#include <vector>
10
11#include "fml/logging.h"
12#include "gtest/gtest.h"
13
32
33namespace impeller {
34namespace testing {
35
36namespace {
37class FakeTexture : public Texture {
38 public:
39 explicit FakeTexture(const TextureDescriptor& desc) : Texture(desc) {}
40
41 ~FakeTexture() override {}
42
43 void SetLabel(std::string_view label) {}
44
45 bool IsValid() const override { return true; }
46
47 ISize GetSize() const override { return {1, 1}; }
48
49 Scalar GetYCoordScale() const override { return 1.0; }
50
51 bool OnSetContents(const uint8_t* contents,
52 size_t length,
53 size_t slice) override {
54 if (GetTextureDescriptor().GetByteSizeOfBaseMipLevel() != length) {
55 return false;
56 }
57 did_set_contents = true;
58 return true;
59 }
60
61 bool OnSetContents(std::shared_ptr<const fml::Mapping> mapping,
62 size_t slice) override {
63 did_set_contents = true;
64 return true;
65 }
66
67 bool did_set_contents = false;
68};
69
70class FakeAllocator : public Allocator,
71 public BackendCast<FakeAllocator, Allocator> {
72 public:
73 FakeAllocator() : Allocator() {}
74
75 uint16_t MinimumBytesPerRow(PixelFormat format) const override { return 0; }
76 ISize GetMaxTextureSizeSupported() const override { return ISize(1, 1); }
77
78 std::shared_ptr<DeviceBuffer> OnCreateBuffer(
79 const DeviceBufferDescriptor& desc) override {
80 return nullptr;
81 }
82 std::shared_ptr<Texture> OnCreateTexture(
83 const TextureDescriptor& desc) override {
84 if (desc.size == ISize{1, 1}) {
85 auto result = std::make_shared<FakeTexture>(desc);
86 textures.push_back(result);
87 return result;
88 }
89 return nullptr;
90 }
91
92 std::vector<std::shared_ptr<FakeTexture>> textures = {};
93};
94
95class FakePipeline : public Pipeline<PipelineDescriptor> {
96 public:
97 FakePipeline(std::weak_ptr<PipelineLibrary> library,
98 const PipelineDescriptor& desc)
99 : Pipeline(std::move(library), desc) {}
100
101 ~FakePipeline() override {}
102
103 bool IsValid() const override { return true; }
104};
105
106class FakeComputePipeline : public Pipeline<ComputePipelineDescriptor> {
107 public:
108 FakeComputePipeline(std::weak_ptr<PipelineLibrary> library,
109 const ComputePipelineDescriptor& desc)
110 : Pipeline(std::move(library), desc) {}
111
112 ~FakeComputePipeline() override {}
113
114 bool IsValid() const override { return true; }
115};
116
117class FakePipelineLibrary : public PipelineLibrary {
118 public:
119 FakePipelineLibrary() {}
120
121 ~FakePipelineLibrary() override {}
122
123 bool IsValid() const override { return true; }
124
125 PipelineFuture<PipelineDescriptor> GetPipeline(
126 PipelineDescriptor descriptor) override {
127 auto pipeline =
128 std::make_shared<FakePipeline>(weak_from_this(), descriptor);
129 std::promise<std::shared_ptr<Pipeline<PipelineDescriptor>>> promise;
130 promise.set_value(std::move(pipeline));
131 return PipelineFuture<PipelineDescriptor>{
132 .descriptor = descriptor,
133 .future =
134 std::shared_future<std::shared_ptr<Pipeline<PipelineDescriptor>>>(
135 promise.get_future())};
136 }
137
138 PipelineFuture<ComputePipelineDescriptor> GetPipeline(
139 ComputePipelineDescriptor descriptor) override {
140 auto pipeline =
141 std::make_shared<FakeComputePipeline>(weak_from_this(), descriptor);
142 std::promise<std::shared_ptr<Pipeline<ComputePipelineDescriptor>>> promise;
143 promise.set_value(std::move(pipeline));
144 return PipelineFuture<ComputePipelineDescriptor>{
145 .descriptor = descriptor,
146 .future = std::shared_future<
147 std::shared_ptr<Pipeline<ComputePipelineDescriptor>>>(
148 promise.get_future())};
149 }
150
151 void RemovePipelinesWithEntryPoint(
152 std::shared_ptr<const ShaderFunction> function) {}
153};
154
155class FakeShaderFunction : public ShaderFunction {
156 public:
157 FakeShaderFunction(UniqueID parent_library_id,
158 std::string name,
159 ShaderStage stage)
160 : ShaderFunction(parent_library_id, std::move(name), stage){};
161
162 ~FakeShaderFunction() override {}
163};
164
165class FakeShaderLibrary : public ShaderLibrary {
166 public:
167 ~FakeShaderLibrary() override {}
168
169 bool IsValid() const override { return true; }
170
171 std::shared_ptr<const ShaderFunction> GetFunction(std::string_view name,
172 ShaderStage stage) {
173 return std::make_shared<FakeShaderFunction>(UniqueID{}, std::string(name),
174 stage);
175 }
176
177 void RegisterFunction(std::string name,
178 ShaderStage stage,
179 std::shared_ptr<fml::Mapping> code,
180 RegistrationCallback callback) override {}
181
182 void UnregisterFunction(std::string name, ShaderStage stage) override {}
183};
184
185class FakeCommandBuffer : public CommandBuffer {
186 public:
187 explicit FakeCommandBuffer(std::weak_ptr<const Context> context)
188 : CommandBuffer(std::move(context)) {}
189
190 ~FakeCommandBuffer() {}
191
192 bool IsValid() const override { return true; }
193
194 void SetLabel(const std::string& label) const override {}
195
196 std::shared_ptr<RenderPass> OnCreateRenderPass(
197 RenderTarget render_target) override {
198 return std::make_shared<RecordingRenderPass>(nullptr, context_.lock(),
199 render_target);
200 }
201
202 std::shared_ptr<BlitPass> OnCreateBlitPass() override { FML_UNREACHABLE() }
203
204 virtual bool OnSubmitCommands(CompletionCallback callback) { return true; }
205
206 void OnWaitUntilScheduled() {}
207
208 std::shared_ptr<ComputePass> OnCreateComputePass() override {
210 }
211};
212
213class FakeContext : public Context,
214 public std::enable_shared_from_this<FakeContext> {
215 public:
216 explicit FakeContext(
217 const std::string& gpu_model = "",
218 PixelFormat default_color_format = PixelFormat::kR8G8B8A8UNormInt)
219 : Context(),
220 allocator_(std::make_shared<FakeAllocator>()),
221 capabilities_(std::shared_ptr<Capabilities>(
222 CapabilitiesBuilder()
223 .SetDefaultColorFormat(default_color_format)
224 .Build())),
225 pipelines_(std::make_shared<FakePipelineLibrary>()),
226 queue_(std::make_shared<CommandQueue>()),
227 shader_library_(std::make_shared<FakeShaderLibrary>()),
228 gpu_model_(gpu_model) {}
229
230 BackendType GetBackendType() const override { return BackendType::kVulkan; }
231 std::string DescribeGpuModel() const override { return gpu_model_; }
232 bool IsValid() const override { return true; }
233 const std::shared_ptr<const Capabilities>& GetCapabilities() const override {
234 return capabilities_;
235 }
236 std::shared_ptr<Allocator> GetResourceAllocator() const override {
237 return allocator_;
238 }
239 std::shared_ptr<ShaderLibrary> GetShaderLibrary() const {
240 return shader_library_;
241 }
242 std::shared_ptr<SamplerLibrary> GetSamplerLibrary() const { return nullptr; }
243 std::shared_ptr<PipelineLibrary> GetPipelineLibrary() const {
244 return pipelines_;
245 }
246 std::shared_ptr<CommandQueue> GetCommandQueue() const { return queue_; }
247 std::shared_ptr<CommandBuffer> CreateCommandBuffer() const {
248 return std::make_shared<FakeCommandBuffer>(shared_from_this());
249 }
250 void Shutdown() {}
251
252 private:
253 std::shared_ptr<Allocator> allocator_;
254 std::shared_ptr<const Capabilities> capabilities_;
255 std::shared_ptr<FakePipelineLibrary> pipelines_;
256 std::shared_ptr<CommandQueue> queue_;
257 std::shared_ptr<ShaderLibrary> shader_library_;
258 std::string gpu_model_;
259};
260} // namespace
261
262TEST(ContentContext, CachesPipelines) {
263 auto context = std::make_shared<FakeContext>();
264
265 auto create_callback = [&]() {
266 return std::make_shared<FakePipeline>(context->GetPipelineLibrary(),
268 };
269
270 ContentContext content_context(context, nullptr);
273
274 auto pipelineA = content_context.GetCachedRuntimeEffectPipeline(
275 "A", optionsA, create_callback);
276
277 auto pipelineA2 = content_context.GetCachedRuntimeEffectPipeline(
278 "A", optionsA, create_callback);
279
280 auto pipelineA3 = content_context.GetCachedRuntimeEffectPipeline(
281 "A", optionsB, create_callback);
282
283 auto pipelineB = content_context.GetCachedRuntimeEffectPipeline(
284 "B", optionsB, create_callback);
285
286 ASSERT_EQ(pipelineA.get(), pipelineA2.get());
287 ASSERT_NE(pipelineA.get(), pipelineA3.get());
288 ASSERT_NE(pipelineB.get(), pipelineA.get());
289}
290
291TEST(ContentContext, InvalidatesAllPipelinesWithSameUniqueNameOnClear) {
292 auto context = std::make_shared<FakeContext>();
293 ContentContext content_context(context, nullptr);
296
297 auto create_callback = [&]() {
298 return std::make_shared<FakePipeline>(context->GetPipelineLibrary(),
300 };
301
302 auto pipelineA = content_context.GetCachedRuntimeEffectPipeline(
303 "A", optionsA, create_callback);
304
305 auto pipelineA2 = content_context.GetCachedRuntimeEffectPipeline(
306 "A", optionsB, create_callback);
307
308 auto pipelineB = content_context.GetCachedRuntimeEffectPipeline(
309 "B", optionsB, create_callback);
310
311 ASSERT_TRUE(pipelineA);
312 ASSERT_TRUE(pipelineA2);
313 ASSERT_TRUE(pipelineB);
314
315 ASSERT_EQ(pipelineA, content_context.GetCachedRuntimeEffectPipeline(
316 "A", optionsA, create_callback));
317 ASSERT_EQ(pipelineA2, content_context.GetCachedRuntimeEffectPipeline(
318 "A", optionsB, create_callback));
319 ASSERT_EQ(pipelineB, content_context.GetCachedRuntimeEffectPipeline(
320 "B", optionsB, create_callback));
321
322 content_context.ClearCachedRuntimeEffectPipeline("A");
323
324 ASSERT_NE(pipelineA, content_context.GetCachedRuntimeEffectPipeline(
325 "A", optionsA, create_callback));
326 ASSERT_NE(pipelineA2, content_context.GetCachedRuntimeEffectPipeline(
327 "A", optionsB, create_callback));
328 ASSERT_EQ(pipelineB, content_context.GetCachedRuntimeEffectPipeline(
329 "B", optionsB, create_callback));
330
331 content_context.ClearCachedRuntimeEffectPipeline("B");
332
333 ASSERT_NE(pipelineB, content_context.GetCachedRuntimeEffectPipeline(
334 "B", optionsB, create_callback));
335}
336
337TEST(ContentContext, InitializeCommonlyUsedShadersIfNeeded) {
338 ScopedValidationFatal fatal_validations;
339 // Set a pixel format that is larger than 32bpp.
340 auto context = std::make_shared<FakeContext>("Mali G70",
342 ContentContext content_context(context, nullptr);
343
344 FakeAllocator& fake_allocator =
345 FakeAllocator::Cast(*context->GetResourceAllocator());
346
347#if IMPELLER_ENABLE_3D
348 EXPECT_EQ(fake_allocator.textures.size(), 2u);
349#else
350 EXPECT_EQ(fake_allocator.textures.size(), 1u);
351#endif // IMPELLER_ENABLE_3D
352}
353
354} // namespace testing
355} // namespace impeller
#define TEST(S, s, D, expected)
void ClearCachedRuntimeEffectPipeline(const std::string &unique_entrypoint_name) const
std::shared_ptr< Pipeline< PipelineDescriptor > > GetCachedRuntimeEffectPipeline(const std::string &unique_entrypoint_name, const ContentContextOptions &options, const std::function< std::shared_ptr< Pipeline< PipelineDescriptor > >()> &create_callback) const
bool did_set_contents
std::vector< std::shared_ptr< FakeTexture > > textures
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
GAsyncResult * result
uint32_t uint32_t * format
#define FML_UNREACHABLE()
Definition logging.h:109
Dart_NativeFunction function
Definition fuchsia.cc:51
const char * name
Definition fuchsia.cc:50
size_t length
Build(configs, env, options)
Definition build.py:232
FunctionPtr GetFunction(const Library &lib, const char *name)
DlSurfaceProvider::BackendType BackendType
float Scalar
Definition scalar.h:18
TSize< int64_t > ISize
Definition size.h:138
static id< MTLCommandBuffer > CreateCommandBuffer(id< MTLCommandQueue > queue)
Definition ref_ptr.h:256