Flutter Engine
 
Loading...
Searching...
No Matches
renderer_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
11#include "impeller/fixtures/array.frag.h"
12#include "impeller/fixtures/array.vert.h"
13#include "impeller/fixtures/baby.frag.h"
14#include "impeller/fixtures/baby.vert.h"
15#include "impeller/fixtures/box_fade.frag.h"
16#include "impeller/fixtures/box_fade.vert.h"
17#include "impeller/fixtures/colors.frag.h"
18#include "impeller/fixtures/colors.vert.h"
19#include "impeller/fixtures/impeller.frag.h"
20#include "impeller/fixtures/impeller.vert.h"
21#include "impeller/fixtures/inactive_uniforms.frag.h"
22#include "impeller/fixtures/inactive_uniforms.vert.h"
23#include "impeller/fixtures/instanced_draw.frag.h"
24#include "impeller/fixtures/instanced_draw.vert.h"
25#include "impeller/fixtures/mipmaps.frag.h"
26#include "impeller/fixtures/mipmaps.vert.h"
27#include "impeller/fixtures/planet.frag.h"
28#include "impeller/fixtures/planet.vert.h"
29#include "impeller/fixtures/sepia.frag.h"
30#include "impeller/fixtures/sepia.vert.h"
31#include "impeller/fixtures/swizzle.frag.h"
32#include "impeller/fixtures/texture.frag.h"
33#include "impeller/fixtures/texture.vert.h"
42#include "third_party/imgui/imgui.h"
43
44// TODO(zanderso): https://github.com/flutter/flutter/issues/127701
45// NOLINTBEGIN(bugprone-unchecked-optional-access)
46
47namespace {
48std::pair<std::shared_ptr<impeller::HostBuffer>,
49 std::shared_ptr<impeller::HostBuffer>>
50createHostBuffers(const std::shared_ptr<impeller::Context>& context) {
51 auto data_host_buffer = impeller::HostBuffer::Create(
52 context->GetResourceAllocator(), context->GetIdleWaiter(),
53 context->GetCapabilities()->GetMinimumUniformAlignment());
54 auto indexes_host_buffer =
55 context->GetCapabilities()->NeedsPartitionedHostBuffer()
57 context->GetResourceAllocator(), context->GetIdleWaiter(),
58 context->GetCapabilities()->GetMinimumUniformAlignment())
59 : data_host_buffer;
60 return {data_host_buffer, indexes_host_buffer};
61}
62} // namespace
63
64namespace impeller {
65namespace testing {
66
67using RendererTest = PlaygroundTest;
69
70TEST_P(RendererTest, CanCreateBoxPrimitive) {
71 using VS = BoxFadeVertexShader;
72 using FS = BoxFadeFragmentShader;
73 auto context = GetContext();
74 ASSERT_TRUE(context);
75 using BoxPipelineBuilder = PipelineBuilder<VS, FS>;
76 auto desc = BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
77 ASSERT_TRUE(desc.has_value());
78 desc->SetSampleCount(SampleCount::kCount4);
79 desc->SetStencilAttachmentDescriptors(std::nullopt);
80
81 // Vertex buffer.
83 vertex_builder.SetLabel("Box");
84 vertex_builder.AddVertices({
85 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
86 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
87 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
88 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
89 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
90 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
91 });
92 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
93 auto boston = CreateTextureForFixture("boston.jpg");
94 ASSERT_TRUE(bridge && boston);
95 raw_ptr<const Sampler> sampler = context->GetSamplerLibrary()->GetSampler({});
96 ASSERT_TRUE(sampler);
97
98 SinglePassCallback callback = [&](RenderPass& pass) {
99 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(context);
100 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
101 static bool wireframe;
102 ImGui::Checkbox("Wireframe", &wireframe);
103 ImGui::End();
104
105 desc->SetPolygonMode(wireframe ? PolygonMode::kLine : PolygonMode::kFill);
106 auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get();
107
108 assert(pipeline && pipeline->IsValid());
109
110 pass.SetCommandLabel("Box");
111 pass.SetPipeline(pipeline);
112 pass.SetVertexBuffer(
113 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator()));
114
115 VS::UniformBuffer uniforms;
116 EXPECT_EQ(pass.GetOrthographicTransform(),
117 Matrix::MakeOrthographic(pass.GetRenderTargetSize()));
118 uniforms.mvp =
119 pass.GetOrthographicTransform() * Matrix::MakeScale(GetContentScale());
120 VS::BindUniformBuffer(pass, data_host_buffer->EmplaceUniform(uniforms));
121
122 FS::FrameInfo frame_info;
123 frame_info.current_time = GetSecondsElapsed();
124 frame_info.cursor_position = GetCursorPosition();
125 frame_info.window_size.x = GetWindowSize().width;
126 frame_info.window_size.y = GetWindowSize().height;
127
128 FS::BindFrameInfo(pass, data_host_buffer->EmplaceUniform(frame_info));
129 FS::BindContents1(pass, boston, sampler);
130 FS::BindContents2(pass, bridge, sampler);
131
132 data_host_buffer->Reset();
133 return pass.Draw().ok();
134 };
135 OpenPlaygroundHere(callback);
136}
137
138TEST_P(RendererTest, BabysFirstTriangle) {
139 auto context = GetContext();
140 ASSERT_TRUE(context);
141
142 // Declare a shorthand for the shaders we are going to use.
143 using VS = BabyVertexShader;
144 using FS = BabyFragmentShader;
145
146 // Create a pipeline descriptor that uses the shaders together and default
147 // initializes the fixed function state.
148 //
149 // If the vertex shader outputs disagree with the fragment shader inputs, this
150 // will be a compile time error.
152 ASSERT_TRUE(desc.has_value());
153
154 // Modify the descriptor for our environment. This is specific to our test.
155 desc->SetSampleCount(SampleCount::kCount4);
156 desc->SetStencilAttachmentDescriptors(std::nullopt);
157
158 // Create a pipeline from our descriptor. This is expensive to do. So just do
159 // it once.
160 auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get();
161
162 // Specify the vertex buffer information.
163 VertexBufferBuilder<VS::PerVertexData> vertex_buffer_builder;
164 vertex_buffer_builder.AddVertices({
165 {{-0.5, -0.5}, Color::Red(), Color::Green()},
166 {{0.0, 0.5}, Color::Green(), Color::Blue()},
167 {{0.5, -0.5}, Color::Blue(), Color::Red()},
168 });
169
170 auto vertex_buffer = vertex_buffer_builder.CreateVertexBuffer(
171 *context->GetResourceAllocator());
172
173 SinglePassCallback callback = [&](RenderPass& pass) {
174 pass.SetPipeline(pipeline);
175 pass.SetVertexBuffer(vertex_buffer);
176
177 FS::FragInfo frag_info;
178 frag_info.time = fml::TimePoint::Now().ToEpochDelta().ToSecondsF();
179
180 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(context);
181 FS::BindFragInfo(pass, data_host_buffer->EmplaceUniform(frag_info));
182
183 return pass.Draw().ok();
184 };
185 OpenPlaygroundHere(callback);
186}
187
188TEST_P(RendererTest, CanRenderPerspectiveCube) {
189 using VS = ColorsVertexShader;
190 using FS = ColorsFragmentShader;
191 auto context = GetContext();
192 ASSERT_TRUE(context);
194 ASSERT_TRUE(desc.has_value());
195 desc->SetCullMode(CullMode::kBackFace);
196 desc->SetWindingOrder(WindingOrder::kCounterClockwise);
197 desc->SetSampleCount(SampleCount::kCount4);
198 desc->ClearStencilAttachments();
199
200 // Setup the vertex layout to take two bindings. The first for positions and
201 // the second for colors.
202 auto vertex_desc = std::make_shared<VertexDescriptor>();
203 ShaderStageIOSlot position_slot = VS::kInputPosition;
204 ShaderStageIOSlot color_slot = VS::kInputColor;
205 position_slot.binding = 0;
206 position_slot.offset = 0;
207 color_slot.binding = 1;
208 color_slot.offset = 0;
209 const std::vector<ShaderStageIOSlot> io_slots = {position_slot, color_slot};
210 const std::vector<ShaderStageBufferLayout> layouts = {
211 ShaderStageBufferLayout{.stride = 12u, .binding = 0},
212 ShaderStageBufferLayout{.stride = 16u, .binding = 1}};
213 vertex_desc->RegisterDescriptorSetLayouts(VS::kDescriptorSetLayouts);
214 vertex_desc->RegisterDescriptorSetLayouts(FS::kDescriptorSetLayouts);
215 vertex_desc->SetStageInputs(io_slots, layouts);
216 desc->SetVertexDescriptor(std::move(vertex_desc));
217 auto pipeline =
218 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
219 ASSERT_TRUE(pipeline);
220
221 struct Cube {
222 Vector3 positions[8] = {
223 // -Z
224 {-1, -1, -1},
225 {1, -1, -1},
226 {1, 1, -1},
227 {-1, 1, -1},
228 // +Z
229 {-1, -1, 1},
230 {1, -1, 1},
231 {1, 1, 1},
232 {-1, 1, 1},
233 };
234 Color colors[8] = {
235 Color::Red(), Color::Yellow(), Color::Green(), Color::Blue(),
236 Color::Green(), Color::Blue(), Color::Red(), Color::Yellow(),
237 };
238 uint16_t indices[36] = {
239 1, 5, 2, 2, 5, 6, // +X
240 4, 0, 7, 7, 0, 3, // -X
241 4, 5, 0, 0, 5, 1, // +Y
242 3, 2, 7, 7, 2, 6, // -Y
243 5, 4, 6, 6, 4, 7, // +Z
244 0, 1, 3, 3, 1, 2, // -Z
245 };
246 } cube;
247
248 auto device_buffer = context->GetResourceAllocator()->CreateBufferWithCopy(
249 reinterpret_cast<uint8_t*>(&cube), sizeof(cube));
250
251 raw_ptr<const Sampler> sampler = context->GetSamplerLibrary()->GetSampler({});
252 ASSERT_TRUE(sampler);
253
254 Vector3 euler_angles;
255 SinglePassCallback callback = [&](RenderPass& pass) {
256 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(context);
257 static Degrees fov_y(60);
258 static Scalar distance = 10;
259
260 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
261 ImGui::SliderFloat("Field of view", &fov_y.degrees, 0, 180);
262 ImGui::SliderFloat("Camera distance", &distance, 0, 30);
263 ImGui::End();
264
265 pass.SetCommandLabel("Perspective Cube");
266 pass.SetPipeline(pipeline);
267
268 std::array<BufferView, 2> vertex_buffers = {
269 BufferView(device_buffer,
270 Range(offsetof(Cube, positions), sizeof(Cube::positions))),
271 BufferView(device_buffer,
272 Range(offsetof(Cube, colors), sizeof(Cube::colors))),
273 };
274
275 BufferView index_buffer(
276 device_buffer, Range(offsetof(Cube, indices), sizeof(Cube::indices)));
277 pass.SetVertexBuffer(vertex_buffers.data(), vertex_buffers.size());
278 pass.SetElementCount(36);
279 pass.SetIndexBuffer(index_buffer, IndexType::k16bit);
280
281 VS::UniformBuffer uniforms;
282 Scalar time = GetSecondsElapsed();
283 euler_angles = Vector3(0.19 * time, 0.7 * time, 0.43 * time);
284
285 uniforms.mvp =
286 Matrix::MakePerspective(fov_y, pass.GetRenderTargetSize(), 0, 10) *
287 Matrix::MakeTranslation({0, 0, distance}) *
288 Matrix::MakeRotationX(Radians(euler_angles.x)) *
289 Matrix::MakeRotationY(Radians(euler_angles.y)) *
290 Matrix::MakeRotationZ(Radians(euler_angles.z));
291 VS::BindUniformBuffer(pass, data_host_buffer->EmplaceUniform(uniforms));
292
293 data_host_buffer->Reset();
294 return pass.Draw().ok();
295 };
296 OpenPlaygroundHere(callback);
297}
298
299TEST_P(RendererTest, CanRenderMultiplePrimitives) {
300 using VS = BoxFadeVertexShader;
301 using FS = BoxFadeFragmentShader;
302 auto context = GetContext();
303 ASSERT_TRUE(context);
304 using BoxPipelineBuilder = PipelineBuilder<VS, FS>;
305 auto desc = BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
306 ASSERT_TRUE(desc.has_value());
307 desc->SetSampleCount(SampleCount::kCount4);
308 desc->SetStencilAttachmentDescriptors(std::nullopt);
309 auto box_pipeline =
310 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
311 ASSERT_TRUE(box_pipeline);
312
313 // Vertex buffer.
315 vertex_builder.SetLabel("Box");
316 vertex_builder.AddVertices({
317 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
318 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
319 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
320 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
321 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
322 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
323 });
324 auto vertex_buffer =
325 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
326 ASSERT_TRUE(vertex_buffer);
327
328 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
329 auto boston = CreateTextureForFixture("boston.jpg");
330 ASSERT_TRUE(bridge && boston);
331 raw_ptr<const Sampler> sampler = context->GetSamplerLibrary()->GetSampler({});
332 ASSERT_TRUE(sampler);
333
334 SinglePassCallback callback = [&](RenderPass& pass) {
335 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(context);
336 for (size_t i = 0; i < 1; i++) {
337 for (size_t j = 0; j < 1; j++) {
338 pass.SetCommandLabel("Box");
339 pass.SetPipeline(box_pipeline);
340 pass.SetVertexBuffer(vertex_buffer);
341
342 FS::FrameInfo frame_info;
343 frame_info.current_time = GetSecondsElapsed();
344 frame_info.cursor_position = GetCursorPosition();
345 frame_info.window_size.x = GetWindowSize().width;
346 frame_info.window_size.y = GetWindowSize().height;
347
348 FS::BindFrameInfo(pass, data_host_buffer->EmplaceUniform(frame_info));
349 FS::BindContents1(pass, boston, sampler);
350 FS::BindContents2(pass, bridge, sampler);
351
352 VS::UniformBuffer uniforms;
353 EXPECT_EQ(pass.GetOrthographicTransform(),
354 Matrix::MakeOrthographic(pass.GetRenderTargetSize()));
355 uniforms.mvp = pass.GetOrthographicTransform() *
356 Matrix::MakeScale(GetContentScale()) *
357 Matrix::MakeTranslation({i * 50.0f, j * 50.0f, 0.0f});
358 VS::BindUniformBuffer(pass, data_host_buffer->EmplaceUniform(uniforms));
359 if (!pass.Draw().ok()) {
360 return false;
361 }
362 }
363 }
364
365 data_host_buffer->Reset();
366 return true;
367 };
368 OpenPlaygroundHere(callback);
369}
370
371TEST_P(RendererTest, CanRenderToTexture) {
372 using VS = BoxFadeVertexShader;
373 using FS = BoxFadeFragmentShader;
374 auto context = GetContext();
375 ASSERT_TRUE(context);
376 using BoxPipelineBuilder = PipelineBuilder<VS, FS>;
377 auto pipeline_desc =
378 BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
379 pipeline_desc->SetSampleCount(SampleCount::kCount1);
380 pipeline_desc->ClearDepthAttachment();
381 pipeline_desc->SetStencilPixelFormat(PixelFormat::kS8UInt);
382
383 ASSERT_TRUE(pipeline_desc.has_value());
384 auto box_pipeline =
385 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
386 ASSERT_TRUE(box_pipeline);
387 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(context);
388
390 vertex_builder.SetLabel("Box");
391 vertex_builder.AddVertices({
392 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
393 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
394 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
395 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
396 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
397 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
398 });
399 auto vertex_buffer =
400 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
401 ASSERT_TRUE(vertex_buffer);
402
403 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
404 auto boston = CreateTextureForFixture("boston.jpg");
405 ASSERT_TRUE(bridge && boston);
406 raw_ptr<const Sampler> sampler = context->GetSamplerLibrary()->GetSampler({});
407 ASSERT_TRUE(sampler);
408
409 std::shared_ptr<RenderPass> r2t_pass;
410 auto cmd_buffer = context->CreateCommandBuffer();
411 ASSERT_TRUE(cmd_buffer);
412 {
413 ColorAttachment color0;
416
417 TextureDescriptor texture_descriptor;
418 ASSERT_NE(pipeline_desc->GetColorAttachmentDescriptor(0u), nullptr);
419 texture_descriptor.format =
420 pipeline_desc->GetColorAttachmentDescriptor(0u)->format;
421 texture_descriptor.storage_mode = StorageMode::kHostVisible;
422 texture_descriptor.size = {400, 400};
423 texture_descriptor.mip_count = 1u;
424 texture_descriptor.usage = TextureUsage::kRenderTarget;
425
426 color0.texture =
427 context->GetResourceAllocator()->CreateTexture(texture_descriptor);
428
429 ASSERT_TRUE(color0.IsValid());
430
431 color0.texture->SetLabel("r2t_target");
432
433 StencilAttachment stencil0;
436 TextureDescriptor stencil_texture_desc;
437 stencil_texture_desc.storage_mode = StorageMode::kDeviceTransient;
438 stencil_texture_desc.size = texture_descriptor.size;
439 stencil_texture_desc.format = PixelFormat::kS8UInt;
440 stencil_texture_desc.usage = TextureUsage::kRenderTarget;
441 stencil0.texture =
442 context->GetResourceAllocator()->CreateTexture(stencil_texture_desc);
443
444 RenderTarget r2t_desc;
445 r2t_desc.SetColorAttachment(color0, 0u);
446 r2t_desc.SetStencilAttachment(stencil0);
447 r2t_pass = cmd_buffer->CreateRenderPass(r2t_desc);
448 ASSERT_TRUE(r2t_pass && r2t_pass->IsValid());
449 }
450
451 r2t_pass->SetCommandLabel("Box");
452 r2t_pass->SetPipeline(box_pipeline);
453 r2t_pass->SetVertexBuffer(vertex_buffer);
454
455 FS::FrameInfo frame_info;
456 frame_info.current_time = GetSecondsElapsed();
457 frame_info.cursor_position = GetCursorPosition();
458 frame_info.window_size.x = GetWindowSize().width;
459 frame_info.window_size.y = GetWindowSize().height;
460
461 FS::BindFrameInfo(*r2t_pass, data_host_buffer->EmplaceUniform(frame_info));
462 FS::BindContents1(*r2t_pass, boston, sampler);
463 FS::BindContents2(*r2t_pass, bridge, sampler);
464
465 VS::UniformBuffer uniforms;
466 uniforms.mvp = Matrix::MakeOrthographic(ISize{1024, 768}) *
467 Matrix::MakeTranslation({50.0f, 50.0f, 0.0f});
468 VS::BindUniformBuffer(*r2t_pass, data_host_buffer->EmplaceUniform(uniforms));
469 ASSERT_TRUE(r2t_pass->Draw().ok());
470 ASSERT_TRUE(r2t_pass->EncodeCommands());
471}
472
473TEST_P(RendererTest, CanRenderInstanced) {
474 if (GetParam() == PlaygroundBackend::kOpenGLES) {
475 GTEST_SKIP() << "Instancing is not supported on OpenGL.";
476 }
477 using VS = InstancedDrawVertexShader;
478 using FS = InstancedDrawFragmentShader;
479
481 builder.AddVertices({
482 VS::PerVertexData{Point{10, 10}},
483 VS::PerVertexData{Point{10, 110}},
484 VS::PerVertexData{Point{110, 10}},
485 VS::PerVertexData{Point{10, 110}},
486 VS::PerVertexData{Point{110, 10}},
487 VS::PerVertexData{Point{110, 110}},
488 });
489
490 ASSERT_NE(GetContext(), nullptr);
491 auto pipeline =
492 GetContext()
493 ->GetPipelineLibrary()
495 *GetContext())
496 ->SetSampleCount(SampleCount::kCount4)
497 .SetStencilAttachmentDescriptors(std::nullopt))
498
499 .Get();
500 ASSERT_TRUE(pipeline && pipeline->IsValid());
501
502 static constexpr size_t kInstancesCount = 5u;
503 VS::InstanceInfo<kInstancesCount> instances;
504 for (size_t i = 0; i < kInstancesCount; i++) {
505 instances.colors[i] = Color::Random();
506 }
507
508 ASSERT_TRUE(OpenPlaygroundHere([&](RenderPass& pass) -> bool {
509 auto [data_host_buffer, indexes_host_buffer] =
510 createHostBuffers(GetContext());
511 pass.SetPipeline(pipeline);
512 pass.SetCommandLabel("InstancedDraw");
513
514 VS::FrameInfo frame_info;
515 EXPECT_EQ(pass.GetOrthographicTransform(),
517 frame_info.mvp =
518 pass.GetOrthographicTransform() * Matrix::MakeScale(GetContentScale());
519 VS::BindFrameInfo(pass, data_host_buffer->EmplaceUniform(frame_info));
520 VS::BindInstanceInfo(pass,
521 data_host_buffer->EmplaceStorageBuffer(instances));
522 pass.SetVertexBuffer(
523 builder.CreateVertexBuffer(*data_host_buffer, *indexes_host_buffer));
524
525 pass.SetInstanceCount(kInstancesCount);
526 pass.Draw();
527
528 data_host_buffer->Reset();
529 return true;
530 }));
531}
532
533TEST_P(RendererTest, CanBlitTextureToTexture) {
534 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
535 GTEST_SKIP() << "Mipmap test shader not supported on GLES.";
536 }
537 auto context = GetContext();
538 ASSERT_TRUE(context);
539
540 using VS = MipmapsVertexShader;
541 using FS = MipmapsFragmentShader;
543 ASSERT_TRUE(desc.has_value());
544 desc->SetSampleCount(SampleCount::kCount4);
545 desc->SetStencilAttachmentDescriptors(std::nullopt);
546 auto mipmaps_pipeline =
547 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
548 ASSERT_TRUE(mipmaps_pipeline);
549
550 TextureDescriptor texture_desc;
553 texture_desc.size = {800, 600};
554 texture_desc.mip_count = 1u;
556 auto texture = context->GetResourceAllocator()->CreateTexture(texture_desc);
557 ASSERT_TRUE(texture);
558
559 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
560 auto boston = CreateTextureForFixture("boston.jpg");
561 ASSERT_TRUE(bridge && boston);
562 raw_ptr<const Sampler> sampler = context->GetSamplerLibrary()->GetSampler({});
563 ASSERT_TRUE(sampler);
564
565 // Vertex buffer.
567 vertex_builder.SetLabel("Box");
568 auto size = Point(boston->GetSize());
569 vertex_builder.AddVertices({
570 {{0, 0}, {0.0, 0.0}}, // 1
571 {{size.x, 0}, {1.0, 0.0}}, // 2
572 {{size.x, size.y}, {1.0, 1.0}}, // 3
573 {{0, 0}, {0.0, 0.0}}, // 1
574 {{size.x, size.y}, {1.0, 1.0}}, // 3
575 {{0, size.y}, {0.0, 1.0}}, // 4
576 });
577 auto vertex_buffer =
578 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
579 ASSERT_TRUE(vertex_buffer);
580
581 Playground::RenderCallback callback = [&](RenderTarget& render_target) {
582 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(context);
583 auto buffer = context->CreateCommandBuffer();
584 if (!buffer) {
585 return false;
586 }
587 buffer->SetLabel("Playground Command Buffer");
588
589 {
590 auto pass = buffer->CreateBlitPass();
591 if (!pass) {
592 return false;
593 }
594 pass->SetLabel("Playground Blit Pass");
595
596 // Blit `bridge` to the top left corner of the texture.
597 pass->AddCopy(bridge, texture);
598
599 if (!pass->EncodeCommands()) {
600 return false;
601 }
602 }
603
604 {
605 auto pass = buffer->CreateRenderPass(render_target);
606 if (!pass) {
607 return false;
608 }
609 pass->SetLabel("Playground Render Pass");
610 {
611 pass->SetCommandLabel("Image");
612 pass->SetPipeline(mipmaps_pipeline);
613 pass->SetVertexBuffer(vertex_buffer);
614
615 VS::FrameInfo frame_info;
616 EXPECT_EQ(pass->GetOrthographicTransform(),
617 Matrix::MakeOrthographic(pass->GetRenderTargetSize()));
618 frame_info.mvp = pass->GetOrthographicTransform() *
619 Matrix::MakeScale(GetContentScale());
620 VS::BindFrameInfo(*pass, data_host_buffer->EmplaceUniform(frame_info));
621
622 FS::FragInfo frag_info;
623 frag_info.lod = 0;
624 FS::BindFragInfo(*pass, data_host_buffer->EmplaceUniform(frag_info));
625
626 auto sampler = context->GetSamplerLibrary()->GetSampler({});
627 FS::BindTex(*pass, texture, sampler);
628
629 pass->Draw();
630 }
631 pass->EncodeCommands();
632 }
633
634 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
635 return false;
636 }
637 data_host_buffer->Reset();
638 return true;
639 };
640 OpenPlaygroundHere(callback);
641}
642
643TEST_P(RendererTest, CanBlitTextureToBuffer) {
644 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
645 GTEST_SKIP() << "Mipmap test shader not supported on GLES.";
646 }
647 auto context = GetContext();
648 ASSERT_TRUE(context);
649
650 using VS = MipmapsVertexShader;
651 using FS = MipmapsFragmentShader;
653 ASSERT_TRUE(desc.has_value());
654 desc->SetSampleCount(SampleCount::kCount4);
655 desc->SetStencilAttachmentDescriptors(std::nullopt);
656 auto mipmaps_pipeline =
657 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
658 ASSERT_TRUE(mipmaps_pipeline);
659
660 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
661 auto boston = CreateTextureForFixture("boston.jpg");
662 ASSERT_TRUE(bridge && boston);
663 raw_ptr<const Sampler> sampler = context->GetSamplerLibrary()->GetSampler({});
664 ASSERT_TRUE(sampler);
665
666 TextureDescriptor texture_desc;
669 texture_desc.size = bridge->GetTextureDescriptor().size;
670 texture_desc.mip_count = 1u;
671 texture_desc.usage = TextureUsage::kRenderTarget |
673 DeviceBufferDescriptor device_buffer_desc;
674 device_buffer_desc.storage_mode = StorageMode::kHostVisible;
675 device_buffer_desc.size =
676 bridge->GetTextureDescriptor().GetByteSizeOfBaseMipLevel();
677 auto device_buffer =
678 context->GetResourceAllocator()->CreateBuffer(device_buffer_desc);
679
680 // Vertex buffer.
682 vertex_builder.SetLabel("Box");
683 auto size = Point(boston->GetSize());
684 vertex_builder.AddVertices({
685 {{0, 0}, {0.0, 0.0}}, // 1
686 {{size.x, 0}, {1.0, 0.0}}, // 2
687 {{size.x, size.y}, {1.0, 1.0}}, // 3
688 {{0, 0}, {0.0, 0.0}}, // 1
689 {{size.x, size.y}, {1.0, 1.0}}, // 3
690 {{0, size.y}, {0.0, 1.0}}, // 4
691 });
692 auto vertex_buffer =
693 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
694 ASSERT_TRUE(vertex_buffer);
695
696 Playground::RenderCallback callback = [&](RenderTarget& render_target) {
697 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(context);
698 {
699 auto buffer = context->CreateCommandBuffer();
700 if (!buffer) {
701 return false;
702 }
703 buffer->SetLabel("Playground Command Buffer");
704 auto pass = buffer->CreateBlitPass();
705 if (!pass) {
706 return false;
707 }
708 pass->SetLabel("Playground Blit Pass");
709
710 // Blit `bridge` to the top left corner of the texture.
711 pass->AddCopy(bridge, device_buffer);
712 pass->EncodeCommands();
713
714 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
715 return false;
716 }
717 }
718
719 {
720 auto buffer = context->CreateCommandBuffer();
721 if (!buffer) {
722 return false;
723 }
724 buffer->SetLabel("Playground Command Buffer");
725
726 auto pass = buffer->CreateRenderPass(render_target);
727 if (!pass) {
728 return false;
729 }
730 pass->SetLabel("Playground Render Pass");
731 {
732 pass->SetCommandLabel("Image");
733 pass->SetPipeline(mipmaps_pipeline);
734 pass->SetVertexBuffer(vertex_buffer);
735
736 VS::FrameInfo frame_info;
737 EXPECT_EQ(pass->GetOrthographicTransform(),
738 Matrix::MakeOrthographic(pass->GetRenderTargetSize()));
739 frame_info.mvp = pass->GetOrthographicTransform() *
740 Matrix::MakeScale(GetContentScale());
741 VS::BindFrameInfo(*pass, data_host_buffer->EmplaceUniform(frame_info));
742
743 FS::FragInfo frag_info;
744 frag_info.lod = 0;
745 FS::BindFragInfo(*pass, data_host_buffer->EmplaceUniform(frag_info));
746
747 raw_ptr<const Sampler> sampler =
748 context->GetSamplerLibrary()->GetSampler({});
749 auto buffer_view = DeviceBuffer::AsBufferView(device_buffer);
750 auto texture =
751 context->GetResourceAllocator()->CreateTexture(texture_desc);
752 if (!texture->SetContents(device_buffer->OnGetContents(),
754 VALIDATION_LOG << "Could not upload texture to device memory";
755 return false;
756 }
757 FS::BindTex(*pass, texture, sampler);
758
759 pass->Draw().ok();
760 }
761 pass->EncodeCommands();
762 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
763 return false;
764 }
765 }
766 data_host_buffer->Reset();
767 return true;
768 };
769 OpenPlaygroundHere(callback);
770}
771
772TEST_P(RendererTest, CanGenerateMipmaps) {
773 if (GetBackend() == PlaygroundBackend::kOpenGLES) {
774 GTEST_SKIP() << "Mipmap test shader not supported on GLES.";
775 }
776 auto context = GetContext();
777 ASSERT_TRUE(context);
778
779 using VS = MipmapsVertexShader;
780 using FS = MipmapsFragmentShader;
782 ASSERT_TRUE(desc.has_value());
783 desc->SetSampleCount(SampleCount::kCount4);
784 desc->SetStencilAttachmentDescriptors(std::nullopt);
785 auto mipmaps_pipeline =
786 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
787 ASSERT_TRUE(mipmaps_pipeline);
788
789 auto boston = CreateTextureForFixture("boston.jpg", true);
790 ASSERT_TRUE(boston);
791
792 // Vertex buffer.
794 vertex_builder.SetLabel("Box");
795 auto size = Point(boston->GetSize());
796 vertex_builder.AddVertices({
797 {{0, 0}, {0.0, 0.0}}, // 1
798 {{size.x, 0}, {1.0, 0.0}}, // 2
799 {{size.x, size.y}, {1.0, 1.0}}, // 3
800 {{0, 0}, {0.0, 0.0}}, // 1
801 {{size.x, size.y}, {1.0, 1.0}}, // 3
802 {{0, size.y}, {0.0, 1.0}}, // 4
803 });
804 auto vertex_buffer =
805 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
806 ASSERT_TRUE(vertex_buffer);
807
808 bool first_frame = true;
809 Playground::RenderCallback callback = [&](RenderTarget& render_target) {
810 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(context);
811 const char* mip_filter_names[] = {"Base", "Nearest", "Linear"};
812 const MipFilter mip_filters[] = {MipFilter::kBase, MipFilter::kNearest,
814 const char* min_filter_names[] = {"Nearest", "Linear"};
815 const MinMagFilter min_filters[] = {MinMagFilter::kNearest,
817
818 // UI state.
819 static int selected_mip_filter = 1;
820 static int selected_min_filter = 0;
821 static float lod = 4.5;
822
823 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
824 ImGui::Combo("Mip filter", &selected_mip_filter, mip_filter_names,
825 sizeof(mip_filter_names) / sizeof(char*));
826 ImGui::Combo("Min filter", &selected_min_filter, min_filter_names,
827 sizeof(min_filter_names) / sizeof(char*));
828 ImGui::SliderFloat("LOD", &lod, 0, boston->GetMipCount() - 1);
829 ImGui::End();
830
831 auto buffer = context->CreateCommandBuffer();
832 if (!buffer) {
833 return false;
834 }
835 buffer->SetLabel("Playground Command Buffer");
836
837 if (first_frame) {
838 auto pass = buffer->CreateBlitPass();
839 if (!pass) {
840 return false;
841 }
842 pass->SetLabel("Playground Blit Pass");
843
844 pass->GenerateMipmap(boston, "Boston Mipmap");
845
846 pass->EncodeCommands();
847 }
848
849 first_frame = false;
850
851 {
852 auto pass = buffer->CreateRenderPass(render_target);
853 if (!pass) {
854 return false;
855 }
856 pass->SetLabel("Playground Render Pass");
857 {
858 pass->SetCommandLabel("Image LOD");
859 pass->SetPipeline(mipmaps_pipeline);
860 pass->SetVertexBuffer(vertex_buffer);
861
862 VS::FrameInfo frame_info;
863 EXPECT_EQ(pass->GetOrthographicTransform(),
864 Matrix::MakeOrthographic(pass->GetRenderTargetSize()));
865 frame_info.mvp = pass->GetOrthographicTransform() *
866 Matrix::MakeScale(GetContentScale());
867 VS::BindFrameInfo(*pass, data_host_buffer->EmplaceUniform(frame_info));
868
869 FS::FragInfo frag_info;
870 frag_info.lod = lod;
871 FS::BindFragInfo(*pass, data_host_buffer->EmplaceUniform(frag_info));
872
873 SamplerDescriptor sampler_desc;
874 sampler_desc.mip_filter = mip_filters[selected_mip_filter];
875 sampler_desc.min_filter = min_filters[selected_min_filter];
876 raw_ptr<const Sampler> sampler =
877 context->GetSamplerLibrary()->GetSampler(sampler_desc);
878 FS::BindTex(*pass, boston, sampler);
879
880 pass->Draw();
881 }
882 pass->EncodeCommands();
883 }
884
885 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
886 return false;
887 }
888 data_host_buffer->Reset();
889 return true;
890 };
891 OpenPlaygroundHere(callback);
892}
893
894TEST_P(RendererTest, TheImpeller) {
895 using VS = ImpellerVertexShader;
896 using FS = ImpellerFragmentShader;
897
898 auto context = GetContext();
899 auto pipeline_descriptor =
901 ASSERT_TRUE(pipeline_descriptor.has_value());
902 pipeline_descriptor->SetSampleCount(SampleCount::kCount4);
903 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
904 auto pipeline =
905 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
906 ASSERT_TRUE(pipeline && pipeline->IsValid());
907
908 auto blue_noise = CreateTextureForFixture("blue_noise.png");
909 SamplerDescriptor noise_sampler_desc;
912 raw_ptr<const Sampler> noise_sampler =
913 context->GetSamplerLibrary()->GetSampler(noise_sampler_desc);
914
915 auto cube_map = CreateTextureCubeForFixture(
916 {"table_mountain_px.png", "table_mountain_nx.png",
917 "table_mountain_py.png", "table_mountain_ny.png",
918 "table_mountain_pz.png", "table_mountain_nz.png"});
919 raw_ptr<const Sampler> cube_map_sampler =
920 context->GetSamplerLibrary()->GetSampler({});
921
922 SinglePassCallback callback = [&](RenderPass& pass) {
923 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(context);
924 auto size = pass.GetRenderTargetSize();
925
926 pass.SetPipeline(pipeline);
927 pass.SetCommandLabel("Impeller SDF scene");
929 builder.AddVertices({{Point()},
930 {Point(0, size.height)},
931 {Point(size.width, 0)},
932 {Point(size.width, 0)},
933 {Point(0, size.height)},
934 {Point(size.width, size.height)}});
935 pass.SetVertexBuffer(
936 builder.CreateVertexBuffer(*data_host_buffer, *indexes_host_buffer));
937
938 VS::FrameInfo frame_info;
939 EXPECT_EQ(pass.GetOrthographicTransform(), Matrix::MakeOrthographic(size));
940 frame_info.mvp = pass.GetOrthographicTransform();
941 VS::BindFrameInfo(pass, data_host_buffer->EmplaceUniform(frame_info));
942
943 FS::FragInfo fs_uniform;
944 fs_uniform.texture_size = Point(size);
945 fs_uniform.time = GetSecondsElapsed();
946 FS::BindFragInfo(pass, data_host_buffer->EmplaceUniform(fs_uniform));
947 FS::BindBlueNoise(pass, blue_noise, noise_sampler);
948 FS::BindCubeMap(pass, cube_map, cube_map_sampler);
949
950 pass.Draw().ok();
951 data_host_buffer->Reset();
952 return true;
953 };
954 OpenPlaygroundHere(callback);
955}
956
958 using VS = PlanetVertexShader;
959 using FS = PlanetFragmentShader;
960
961 auto context = GetContext();
962 auto pipeline_descriptor =
964 ASSERT_TRUE(pipeline_descriptor.has_value());
965 pipeline_descriptor->SetSampleCount(SampleCount::kCount4);
966 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
967 auto pipeline =
968 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
969 ASSERT_TRUE(pipeline && pipeline->IsValid());
970
971 SinglePassCallback callback = [&](RenderPass& pass) {
972 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(context);
973 static Scalar speed = 0.1;
974 static Scalar planet_size = 550.0;
975 static bool show_normals = false;
976 static bool show_noise = false;
977 static Scalar seed_value = 42.0;
978
979 auto size = pass.GetRenderTargetSize();
980
981 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
982 ImGui::SliderFloat("Speed", &speed, 0.0, 10.0);
983 ImGui::SliderFloat("Planet Size", &planet_size, 0.1, 1000);
984 ImGui::Checkbox("Show Normals", &show_normals);
985 ImGui::Checkbox("Show Noise", &show_noise);
986 ImGui::InputFloat("Seed Value", &seed_value);
987 ImGui::End();
988
989 pass.SetPipeline(pipeline);
990 pass.SetCommandLabel("Planet scene");
992 builder.AddVertices({{Point()},
993 {Point(0, size.height)},
994 {Point(size.width, 0)},
995 {Point(size.width, 0)},
996 {Point(0, size.height)},
997 {Point(size.width, size.height)}});
998 pass.SetVertexBuffer(
999 builder.CreateVertexBuffer(*data_host_buffer, *indexes_host_buffer));
1000
1001 VS::FrameInfo frame_info;
1002 EXPECT_EQ(pass.GetOrthographicTransform(), Matrix::MakeOrthographic(size));
1003 frame_info.mvp = pass.GetOrthographicTransform();
1004 VS::BindFrameInfo(pass, data_host_buffer->EmplaceUniform(frame_info));
1005
1006 FS::FragInfo fs_uniform;
1007 fs_uniform.resolution = Point(size);
1008 fs_uniform.time = GetSecondsElapsed();
1009 fs_uniform.speed = speed;
1010 fs_uniform.planet_size = planet_size;
1011 fs_uniform.show_normals = show_normals ? 1.0 : 0.0;
1012 fs_uniform.show_noise = show_noise ? 1.0 : 0.0;
1013 fs_uniform.seed_value = seed_value;
1014 FS::BindFragInfo(pass, data_host_buffer->EmplaceUniform(fs_uniform));
1015
1016 pass.Draw().ok();
1017 data_host_buffer->Reset();
1018 return true;
1019 };
1020 OpenPlaygroundHere(callback);
1021}
1022
1023TEST_P(RendererTest, ArrayUniforms) {
1024 using VS = ArrayVertexShader;
1025 using FS = ArrayFragmentShader;
1026
1027 auto context = GetContext();
1028 auto pipeline_descriptor =
1030 ASSERT_TRUE(pipeline_descriptor.has_value());
1031 pipeline_descriptor->SetSampleCount(SampleCount::kCount4);
1032 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
1033 auto pipeline =
1034 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
1035 ASSERT_TRUE(pipeline && pipeline->IsValid());
1036
1037 SinglePassCallback callback = [&](RenderPass& pass) {
1038 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(context);
1039 auto size = pass.GetRenderTargetSize();
1040
1041 pass.SetPipeline(pipeline);
1042 pass.SetCommandLabel("Google Dots");
1044 builder.AddVertices({{Point()},
1045 {Point(0, size.height)},
1046 {Point(size.width, 0)},
1047 {Point(size.width, 0)},
1048 {Point(0, size.height)},
1049 {Point(size.width, size.height)}});
1050 pass.SetVertexBuffer(
1051 builder.CreateVertexBuffer(*data_host_buffer, *indexes_host_buffer));
1052
1053 VS::FrameInfo frame_info;
1054 EXPECT_EQ(pass.GetOrthographicTransform(), Matrix::MakeOrthographic(size));
1055 frame_info.mvp =
1056 pass.GetOrthographicTransform() * Matrix::MakeScale(GetContentScale());
1057 VS::BindFrameInfo(pass, data_host_buffer->EmplaceUniform(frame_info));
1058
1059 auto time = GetSecondsElapsed();
1060 auto y_pos = [&time](float x) {
1061 return 400 + 10 * std::cos(time * 5 + x / 6);
1062 };
1063
1064 FS::FragInfo fs_uniform = {
1065 .circle_positions = {Point(430, y_pos(0)), Point(480, y_pos(1)),
1066 Point(530, y_pos(2)), Point(580, y_pos(3))},
1067 .colors = {Color::MakeRGBA8(66, 133, 244, 255),
1068 Color::MakeRGBA8(219, 68, 55, 255),
1069 Color::MakeRGBA8(244, 180, 0, 255),
1070 Color::MakeRGBA8(15, 157, 88, 255)},
1071 };
1072 FS::BindFragInfo(pass, data_host_buffer->EmplaceUniform(fs_uniform));
1073
1074 pass.Draw();
1075 data_host_buffer->Reset();
1076 return true;
1077 };
1078 OpenPlaygroundHere(callback);
1079}
1080
1081TEST_P(RendererTest, InactiveUniforms) {
1082 using VS = InactiveUniformsVertexShader;
1083 using FS = InactiveUniformsFragmentShader;
1084
1085 auto context = GetContext();
1086 auto pipeline_descriptor =
1088 ASSERT_TRUE(pipeline_descriptor.has_value());
1089 pipeline_descriptor->SetSampleCount(SampleCount::kCount4);
1090 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
1091 auto pipeline =
1092 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
1093 ASSERT_TRUE(pipeline && pipeline->IsValid());
1094
1095 SinglePassCallback callback = [&](RenderPass& pass) {
1096 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(context);
1097 auto size = pass.GetRenderTargetSize();
1098
1099 pass.SetPipeline(pipeline);
1100 pass.SetCommandLabel("Inactive Uniform");
1101
1103 builder.AddVertices({{Point()},
1104 {Point(0, size.height)},
1105 {Point(size.width, 0)},
1106 {Point(size.width, 0)},
1107 {Point(0, size.height)},
1108 {Point(size.width, size.height)}});
1109 pass.SetVertexBuffer(
1110 builder.CreateVertexBuffer(*data_host_buffer, *indexes_host_buffer));
1111
1112 VS::FrameInfo frame_info;
1113 EXPECT_EQ(pass.GetOrthographicTransform(), Matrix::MakeOrthographic(size));
1114 frame_info.mvp =
1115 pass.GetOrthographicTransform() * Matrix::MakeScale(GetContentScale());
1116 VS::BindFrameInfo(pass, data_host_buffer->EmplaceUniform(frame_info));
1117
1118 FS::FragInfo fs_uniform = {.unused_color = Color::Red(),
1119 .color = Color::Green()};
1120 FS::BindFragInfo(pass, data_host_buffer->EmplaceUniform(fs_uniform));
1121
1122 pass.Draw().ok();
1123 data_host_buffer->Reset();
1124 return true;
1125 };
1126 OpenPlaygroundHere(callback);
1127}
1128
1129TEST_P(RendererTest, DefaultIndexSize) {
1130 using VS = BoxFadeVertexShader;
1131
1132 // Default to 16bit index buffer size, as this is a reasonable default and
1133 // supported on all backends without extensions.
1135 vertex_builder.AppendIndex(0u);
1136 ASSERT_EQ(vertex_builder.GetIndexType(), IndexType::k16bit);
1137}
1138
1139TEST_P(RendererTest, DefaultIndexBehavior) {
1140 using VS = BoxFadeVertexShader;
1141
1142 // Do not create any index buffer if no indices were provided.
1144 ASSERT_EQ(vertex_builder.GetIndexType(), IndexType::kNone);
1145}
1146
1148 // Does not create index buffer if one is provided.
1149 using VS = BoxFadeVertexShader;
1151 vertex_builder.SetLabel("Box");
1152 vertex_builder.AddVertices({
1153 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1154 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
1155 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1156 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
1157 });
1158 vertex_builder.AppendIndex(0);
1159 vertex_builder.AppendIndex(1);
1160 vertex_builder.AppendIndex(2);
1161 vertex_builder.AppendIndex(1);
1162 vertex_builder.AppendIndex(2);
1163 vertex_builder.AppendIndex(3);
1164
1165 ASSERT_EQ(vertex_builder.GetIndexCount(), 6u);
1166 ASSERT_EQ(vertex_builder.GetVertexCount(), 4u);
1167}
1168
1170 public:
1172 labels_.push_back("Never");
1173 functions_.push_back(CompareFunction::kNever);
1174 labels_.push_back("Always");
1175 functions_.push_back(CompareFunction::kAlways);
1176 labels_.push_back("Less");
1177 functions_.push_back(CompareFunction::kLess);
1178 labels_.push_back("Equal");
1179 functions_.push_back(CompareFunction::kEqual);
1180 labels_.push_back("LessEqual");
1181 functions_.push_back(CompareFunction::kLessEqual);
1182 labels_.push_back("Greater");
1183 functions_.push_back(CompareFunction::kGreater);
1184 labels_.push_back("NotEqual");
1185 functions_.push_back(CompareFunction::kNotEqual);
1186 labels_.push_back("GreaterEqual");
1187 functions_.push_back(CompareFunction::kGreaterEqual);
1188 assert(labels_.size() == functions_.size());
1189 }
1190
1191 const char* const* labels() const { return &labels_[0]; }
1192
1193 int size() const { return labels_.size(); }
1194
1195 int IndexOf(CompareFunction func) const {
1196 for (size_t i = 0; i < functions_.size(); i++) {
1197 if (functions_[i] == func) {
1198 return i;
1199 }
1200 }
1202 return -1;
1203 }
1204
1205 CompareFunction FunctionOf(int index) const { return functions_[index]; }
1206
1207 private:
1208 std::vector<const char*> labels_;
1209 std::vector<CompareFunction> functions_;
1210};
1211
1214 return data;
1215}
1216
1217TEST_P(RendererTest, StencilMask) {
1218 using VS = BoxFadeVertexShader;
1219 using FS = BoxFadeFragmentShader;
1220 auto context = GetContext();
1221 ASSERT_TRUE(context);
1222 using BoxFadePipelineBuilder = PipelineBuilder<VS, FS>;
1223 auto desc = BoxFadePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
1224 ASSERT_TRUE(desc.has_value());
1225
1226 // Vertex buffer.
1228 vertex_builder.SetLabel("Box");
1229 vertex_builder.AddVertices({
1230 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1231 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
1232 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1233 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1234 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1235 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
1236 });
1237 auto vertex_buffer =
1238 vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
1239 ASSERT_TRUE(vertex_buffer);
1240
1241 desc->SetSampleCount(SampleCount::kCount4);
1242 desc->SetStencilAttachmentDescriptors(std::nullopt);
1243
1244 auto bridge = CreateTextureForFixture("bay_bridge.jpg");
1245 auto boston = CreateTextureForFixture("boston.jpg");
1246 ASSERT_TRUE(bridge && boston);
1247 raw_ptr<const Sampler> sampler = context->GetSamplerLibrary()->GetSampler({});
1248 ASSERT_TRUE(sampler);
1249
1250 static bool mirror = false;
1251 static int stencil_reference_write = 0xFF;
1252 static int stencil_reference_read = 0x1;
1253 std::vector<uint8_t> stencil_contents;
1254 static int last_stencil_contents_reference_value = 0;
1255 static int current_front_compare =
1257 static int current_back_compare =
1259
1260 Playground::RenderCallback callback = [&](RenderTarget& render_target) {
1261 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(context);
1262 auto buffer = context->CreateCommandBuffer();
1263 if (!buffer) {
1264 return false;
1265 }
1266 buffer->SetLabel("Playground Command Buffer");
1267
1268 {
1269 // Configure the stencil attachment for the test.
1270 RenderTarget::AttachmentConfig stencil_config;
1271 stencil_config.load_action = LoadAction::kLoad;
1272 stencil_config.store_action = StoreAction::kDontCare;
1273 stencil_config.storage_mode = StorageMode::kHostVisible;
1274 render_target.SetupDepthStencilAttachments(
1275 *context, *context->GetResourceAllocator(),
1276 render_target.GetRenderTargetSize(), true, "stencil", stencil_config);
1277 // Fill the stencil buffer with an checkerboard pattern.
1278 const auto target_width = render_target.GetRenderTargetSize().width;
1279 const auto target_height = render_target.GetRenderTargetSize().height;
1280 const size_t target_size = target_width * target_height;
1281 if (stencil_contents.size() != target_size ||
1282 last_stencil_contents_reference_value != stencil_reference_write) {
1283 stencil_contents.resize(target_size);
1284 last_stencil_contents_reference_value = stencil_reference_write;
1285 for (int y = 0; y < target_height; y++) {
1286 for (int x = 0; x < target_width; x++) {
1287 const auto index = y * target_width + x;
1288 const auto kCheckSize = 64;
1289 const auto value =
1290 (((y / kCheckSize) + (x / kCheckSize)) % 2 == 0) *
1291 stencil_reference_write;
1292 stencil_contents[index] = value;
1293 }
1294 }
1295 }
1296 if (!render_target.GetStencilAttachment()->texture->SetContents(
1297 stencil_contents.data(), stencil_contents.size(), 0, false)) {
1298 VALIDATION_LOG << "Could not upload stencil contents to device memory";
1299 return false;
1300 }
1301 auto pass = buffer->CreateRenderPass(render_target);
1302 if (!pass) {
1303 return false;
1304 }
1305 pass->SetLabel("Stencil Buffer");
1306 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1307 ImGui::SliderInt("Stencil Write Value", &stencil_reference_write, 0,
1308 0xFF);
1309 ImGui::SliderInt("Stencil Compare Value", &stencil_reference_read, 0,
1310 0xFF);
1311 ImGui::Checkbox("Back face mode", &mirror);
1312 ImGui::ListBox("Front face compare function", &current_front_compare,
1313 CompareFunctionUI().labels(), CompareFunctionUI().size());
1314 ImGui::ListBox("Back face compare function", &current_back_compare,
1315 CompareFunctionUI().labels(), CompareFunctionUI().size());
1316 ImGui::End();
1317
1319 front.stencil_compare =
1320 CompareFunctionUI().FunctionOf(current_front_compare);
1322 back.stencil_compare =
1323 CompareFunctionUI().FunctionOf(current_back_compare);
1324 desc->SetStencilAttachmentDescriptors(front, back);
1325 auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get();
1326
1327 assert(pipeline && pipeline->IsValid());
1328
1329 pass->SetCommandLabel("Box");
1330 pass->SetPipeline(pipeline);
1331 pass->SetStencilReference(stencil_reference_read);
1332 pass->SetVertexBuffer(vertex_buffer);
1333
1334 VS::UniformBuffer uniforms;
1335 EXPECT_EQ(pass->GetOrthographicTransform(),
1336 Matrix::MakeOrthographic(pass->GetRenderTargetSize()));
1337 uniforms.mvp = pass->GetOrthographicTransform() *
1338 Matrix::MakeScale(GetContentScale());
1339 if (mirror) {
1340 uniforms.mvp = Matrix::MakeScale(Vector2(-1, 1)) * uniforms.mvp;
1341 }
1342 VS::BindUniformBuffer(*pass, data_host_buffer->EmplaceUniform(uniforms));
1343
1344 FS::FrameInfo frame_info;
1345 frame_info.current_time = GetSecondsElapsed();
1346 frame_info.cursor_position = GetCursorPosition();
1347 frame_info.window_size.x = GetWindowSize().width;
1348 frame_info.window_size.y = GetWindowSize().height;
1349
1350 FS::BindFrameInfo(*pass, data_host_buffer->EmplaceUniform(frame_info));
1351 FS::BindContents1(*pass, boston, sampler);
1352 FS::BindContents2(*pass, bridge, sampler);
1353 if (!pass->Draw().ok()) {
1354 return false;
1355 }
1356 pass->EncodeCommands();
1357 }
1358
1359 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
1360 return false;
1361 }
1362 data_host_buffer->Reset();
1363 return true;
1364 };
1365 OpenPlaygroundHere(callback);
1366}
1367
1368TEST_P(RendererTest, CanLookupRenderTargetProperties) {
1369 auto context = GetContext();
1370 auto cmd_buffer = context->CreateCommandBuffer();
1371 auto render_target_cache = std::make_shared<RenderTargetAllocator>(
1372 GetContext()->GetResourceAllocator());
1373
1374 auto render_target = render_target_cache->CreateOffscreen(
1375 *context, {100, 100}, /*mip_count=*/1);
1376 auto render_pass = cmd_buffer->CreateRenderPass(render_target);
1377
1378 EXPECT_EQ(render_pass->GetSampleCount(), render_target.GetSampleCount());
1379 EXPECT_EQ(render_pass->GetRenderTargetPixelFormat(),
1380 render_target.GetRenderTargetPixelFormat());
1381 EXPECT_EQ(render_pass->HasStencilAttachment(),
1382 render_target.GetStencilAttachment().has_value());
1383 EXPECT_EQ(render_pass->GetRenderTargetSize(),
1384 render_target.GetRenderTargetSize());
1385 render_pass->EncodeCommands();
1386}
1387
1389 RenderTargetCreateOffscreenMSAASetsDefaultDepthStencilFormat) {
1390 auto context = GetContext();
1391 auto render_target_cache = std::make_shared<RenderTargetAllocator>(
1392 GetContext()->GetResourceAllocator());
1393
1394 RenderTarget render_target = render_target_cache->CreateOffscreenMSAA(
1395 *context, {100, 100}, /*mip_count=*/1);
1396 EXPECT_EQ(render_target.GetDepthAttachment()
1397 ->texture->GetTextureDescriptor()
1398 .format,
1399 GetContext()->GetCapabilities()->GetDefaultDepthStencilFormat());
1400}
1401
1402template <class VertexShader, class FragmentShader>
1403std::shared_ptr<Pipeline<PipelineDescriptor>> CreateDefaultPipeline(
1404 const std::shared_ptr<Context>& context) {
1405 using TexturePipelineBuilder = PipelineBuilder<VertexShader, FragmentShader>;
1406 auto pipeline_desc =
1407 TexturePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
1408 if (!pipeline_desc.has_value()) {
1409 return nullptr;
1410 }
1411 pipeline_desc->SetSampleCount(SampleCount::kCount4);
1412 pipeline_desc->SetStencilAttachmentDescriptors(std::nullopt);
1413 auto pipeline =
1414 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
1415 if (!pipeline || !pipeline->IsValid()) {
1416 return nullptr;
1417 }
1418 return pipeline;
1419}
1420
1421TEST_P(RendererTest, CanSepiaToneWithSubpasses) {
1422 // Define shader types
1423 using TextureVS = TextureVertexShader;
1424 using TextureFS = TextureFragmentShader;
1425
1426 using SepiaVS = SepiaVertexShader;
1427 using SepiaFS = SepiaFragmentShader;
1428
1429 auto context = GetContext();
1430 ASSERT_TRUE(context);
1431
1432 if (!context->GetCapabilities()->SupportsFramebufferFetch()) {
1433 GTEST_SKIP() << "This test uses framebuffer fetch and the backend doesn't "
1434 "support it.";
1435 return;
1436 }
1437
1438 // Create pipelines.
1439 auto texture_pipeline = CreateDefaultPipeline<TextureVS, TextureFS>(context);
1440 auto sepia_pipeline = CreateDefaultPipeline<SepiaVS, SepiaFS>(context);
1441
1442 ASSERT_TRUE(texture_pipeline);
1443 ASSERT_TRUE(sepia_pipeline);
1444
1445 // Vertex buffer builders.
1447 texture_vtx_builder.AddVertices({
1448 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1449 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
1450 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1451 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1452 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1453 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
1454 });
1455
1457 sepia_vtx_builder.AddVertices({
1458 {{100, 100, 0.0}}, // 1
1459 {{800, 100, 0.0}}, // 2
1460 {{800, 800, 0.0}}, // 3
1461 {{100, 100, 0.0}}, // 1
1462 {{800, 800, 0.0}}, // 3
1463 {{100, 800, 0.0}}, // 4
1464 });
1465
1466 auto boston = CreateTextureForFixture("boston.jpg");
1467 ASSERT_TRUE(boston);
1468
1469 const auto& sampler = context->GetSamplerLibrary()->GetSampler({});
1470 ASSERT_TRUE(sampler);
1471
1472 SinglePassCallback callback = [&](RenderPass& pass) {
1474 context->GetResourceAllocator(), context->GetIdleWaiter(),
1475 context->GetCapabilities()->GetMinimumUniformAlignment());
1476
1477 // Draw the texture.
1478 {
1479 pass.SetPipeline(texture_pipeline);
1480 pass.SetVertexBuffer(texture_vtx_builder.CreateVertexBuffer(
1481 *context->GetResourceAllocator()));
1482 TextureVS::UniformBuffer uniforms;
1483 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1484 Matrix::MakeScale(GetContentScale());
1485 TextureVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1486 TextureFS::BindTextureContents(pass, boston, sampler);
1487 if (!pass.Draw().ok()) {
1488 return false;
1489 }
1490 }
1491
1492 // Draw the sepia toner.
1493 {
1494 pass.SetPipeline(sepia_pipeline);
1495 pass.SetVertexBuffer(sepia_vtx_builder.CreateVertexBuffer(
1496 *context->GetResourceAllocator()));
1497 SepiaVS::UniformBuffer uniforms;
1498 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1499 Matrix::MakeScale(GetContentScale());
1500 SepiaVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1501 if (!pass.Draw().ok()) {
1502 return false;
1503 }
1504 }
1505
1506 return true;
1507 };
1508 OpenPlaygroundHere(callback);
1509}
1510
1511TEST_P(RendererTest, CanSepiaToneThenSwizzleWithSubpasses) {
1512 // Define shader types
1513 using TextureVS = TextureVertexShader;
1514 using TextureFS = TextureFragmentShader;
1515
1516 using SwizzleVS = SepiaVertexShader;
1517 using SwizzleFS = SwizzleFragmentShader;
1518
1519 using SepiaVS = SepiaVertexShader;
1520 using SepiaFS = SepiaFragmentShader;
1521
1522 auto context = GetContext();
1523 ASSERT_TRUE(context);
1524
1525 if (!context->GetCapabilities()->SupportsFramebufferFetch()) {
1526 GTEST_SKIP() << "This test uses framebuffer fetch and the backend doesn't "
1527 "support it.";
1528 return;
1529 }
1530
1531 // Create pipelines.
1532 auto texture_pipeline = CreateDefaultPipeline<TextureVS, TextureFS>(context);
1533 auto swizzle_pipeline = CreateDefaultPipeline<SwizzleVS, SwizzleFS>(context);
1534 auto sepia_pipeline = CreateDefaultPipeline<SepiaVS, SepiaFS>(context);
1535
1536 ASSERT_TRUE(texture_pipeline);
1537 ASSERT_TRUE(swizzle_pipeline);
1538 ASSERT_TRUE(sepia_pipeline);
1539
1540 // Vertex buffer builders.
1542 texture_vtx_builder.AddVertices({
1543 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1544 {{800, 100, 0.0}, {1.0, 0.0}}, // 2
1545 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1546 {{100, 100, 0.0}, {0.0, 0.0}}, // 1
1547 {{800, 800, 0.0}, {1.0, 1.0}}, // 3
1548 {{100, 800, 0.0}, {0.0, 1.0}}, // 4
1549 });
1550
1552 sepia_vtx_builder.AddVertices({
1553 {{100, 100, 0.0}}, // 1
1554 {{800, 100, 0.0}}, // 2
1555 {{800, 800, 0.0}}, // 3
1556 {{100, 100, 0.0}}, // 1
1557 {{800, 800, 0.0}}, // 3
1558 {{100, 800, 0.0}}, // 4
1559 });
1560
1561 auto boston = CreateTextureForFixture("boston.jpg");
1562 ASSERT_TRUE(boston);
1563
1564 const auto& sampler = context->GetSamplerLibrary()->GetSampler({});
1565 ASSERT_TRUE(sampler);
1566
1567 SinglePassCallback callback = [&](RenderPass& pass) {
1568 auto data_buffer = HostBuffer::Create(
1569 context->GetResourceAllocator(), context->GetIdleWaiter(),
1570 context->GetCapabilities()->GetMinimumUniformAlignment());
1571
1572 // Draw the texture.
1573 {
1574 pass.SetPipeline(texture_pipeline);
1575 pass.SetVertexBuffer(texture_vtx_builder.CreateVertexBuffer(
1576 *context->GetResourceAllocator()));
1577 TextureVS::UniformBuffer uniforms;
1578 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1579 Matrix::MakeScale(GetContentScale());
1580 TextureVS::BindUniformBuffer(pass, data_buffer->EmplaceUniform(uniforms));
1581 TextureFS::BindTextureContents(pass, boston, sampler);
1582 if (!pass.Draw().ok()) {
1583 return false;
1584 }
1585 }
1586
1587 // Draw the sepia toner.
1588 {
1589 pass.SetPipeline(sepia_pipeline);
1590 pass.SetVertexBuffer(sepia_vtx_builder.CreateVertexBuffer(
1591 *context->GetResourceAllocator()));
1592 SepiaVS::UniformBuffer uniforms;
1593 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1594 Matrix::MakeScale(GetContentScale());
1595 SepiaVS::BindUniformBuffer(pass, data_buffer->EmplaceUniform(uniforms));
1596 if (!pass.Draw().ok()) {
1597 return false;
1598 }
1599 }
1600
1601 // Draw the swizzle.
1602 {
1603 pass.SetPipeline(swizzle_pipeline);
1604 pass.SetVertexBuffer(sepia_vtx_builder.CreateVertexBuffer(
1605 *context->GetResourceAllocator()));
1606 SwizzleVS::UniformBuffer uniforms;
1607 uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
1608 Matrix::MakeScale(GetContentScale());
1609 SwizzleVS::BindUniformBuffer(pass, data_buffer->EmplaceUniform(uniforms));
1610 if (!pass.Draw().ok()) {
1611 return false;
1612 }
1613 }
1614
1615 return true;
1616 };
1617 OpenPlaygroundHere(callback);
1618}
1619
1620TEST_P(RendererTest, BindingNullTexturesDoesNotCrash) {
1621 using FS = BoxFadeFragmentShader;
1622
1623 auto context = GetContext();
1624 raw_ptr<const Sampler> sampler = context->GetSamplerLibrary()->GetSampler({});
1625 auto command_buffer = context->CreateCommandBuffer();
1626
1627 RenderTargetAllocator allocator(context->GetResourceAllocator());
1628 RenderTarget target = allocator.CreateOffscreen(*context, {1, 1}, 1);
1629
1630 auto pass = command_buffer->CreateRenderPass(target);
1631 EXPECT_FALSE(FS::BindContents2(*pass, nullptr, sampler));
1632}
1633
1634} // namespace testing
1635} // namespace impeller
1636
1637// NOLINTEND(bugprone-unchecked-optional-access)
BufferView buffer_view
constexpr double ToSecondsF() const
Definition time_delta.h:71
constexpr TimeDelta ToEpochDelta() const
Definition time_point.h:52
static TimePoint Now()
Definition time_point.cc:49
static BufferView AsBufferView(std::shared_ptr< DeviceBuffer > buffer)
Create a buffer view of this entire buffer.
static std::shared_ptr< HostBuffer > Create(const std::shared_ptr< Allocator > &allocator, const std::shared_ptr< const IdleWaiter > &idle_waiter, size_t minimum_uniform_alignment)
std::function< bool(RenderTarget &render_target)> RenderCallback
Definition playground.h:81
Render passes encode render commands directed as one specific render target into an underlying comman...
Definition render_pass.h:30
virtual bool SetVertexBuffer(VertexBuffer buffer)
Specify the vertex and index buffer to use for this command.
const Matrix & GetOrthographicTransform() const
virtual void SetPipeline(PipelineRef pipeline)
The pipeline to use for this command.
ISize GetRenderTargetSize() const
virtual void SetInstanceCount(size_t count)
virtual fml::Status Draw()
Record the currently pending command.
virtual void SetCommandLabel(std::string_view label)
The debugging label to use for the command.
a wrapper around the impeller [Allocator] instance that can be used to provide caching of allocated r...
virtual RenderTarget CreateOffscreen(const Context &context, ISize size, int mip_count, std::string_view label="Offscreen", RenderTarget::AttachmentConfig color_attachment_config=RenderTarget::kDefaultColorAttachmentConfig, std::optional< RenderTarget::AttachmentConfig > stencil_attachment_config=RenderTarget::kDefaultStencilAttachmentConfig, const std::shared_ptr< Texture > &existing_color_texture=nullptr, const std::shared_ptr< Texture > &existing_depth_stencil_texture=nullptr)
RenderTarget & SetColorAttachment(const ColorAttachment &attachment, size_t index)
RenderTarget & SetStencilAttachment(std::optional< StencilAttachment > attachment)
const std::optional< DepthAttachment > & GetDepthAttachment() const
VertexBuffer CreateVertexBuffer(HostBuffer &data_host_buffer, HostBuffer &indexes_host_buffer) const
VertexBufferBuilder & AppendIndex(IndexType_ index)
void SetLabel(const std::string &label)
VertexBufferBuilder & AddVertices(std::initializer_list< VertexType_ > vertices)
constexpr impeller::IndexType GetIndexType() const
A wrapper around a raw ptr that adds additional unopt mode only checks.
Definition raw_ptr.h:15
CompareFunction FunctionOf(int index) const
int IndexOf(CompareFunction func) const
int32_t value
int32_t x
uint32_t * target
FlutterDesktopBinaryReply callback
#define FML_UNREACHABLE()
Definition logging.h:128
FlTexture * texture
double y
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
Definition switch_defs.h:36
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set profile Make the profiler discard new samples once the profiler sample buffer is full When this flag is not the profiler sample buffer is used as a ring buffer
Definition switch_defs.h:98
static const CompareFunctionUIData & CompareFunctionUI()
TEST_P(AiksTest, DrawAtlasNoColor)
Point Vector2
Definition point.h:331
float Scalar
Definition scalar.h:19
@ kNone
Does not use the index buffer.
LinePipeline::FragmentShader FS
CompareFunction
Definition formats.h:552
@ kEqual
Comparison test passes if new_value == current_value.
@ kLessEqual
Comparison test passes if new_value <= current_value.
@ kGreaterEqual
Comparison test passes if new_value >= current_value.
@ kAlways
Comparison test passes always passes.
@ kLess
Comparison test passes if new_value < current_value.
@ kGreater
Comparison test passes if new_value > current_value.
@ kNotEqual
Comparison test passes if new_value != current_value.
@ kNever
Comparison test never passes.
MipFilter
Options for selecting and filtering between mipmap levels.
Definition formats.h:425
@ kLinear
Sample from the two nearest mip levels and linearly interpolate.
@ kBase
The texture is sampled as if it only had a single mipmap level.
@ kNearest
The nearst mipmap level is selected.
LinePipeline::VertexShader VS
static std::unique_ptr< PipelineT > CreateDefaultPipeline(const Context &context)
MinMagFilter
Describes how the texture should be sampled when the texture is being shrunk (minified) or expanded (...
Definition formats.h:415
@ kNearest
Select nearest to the sample point. Most widely supported.
#define INSTANTIATE_PLAYGROUND_SUITE(playground)
bool IsValid() const
Definition formats.cc:26
LoadAction load_action
Definition formats.h:659
std::shared_ptr< Texture > texture
Definition formats.h:657
StoreAction store_action
Definition formats.h:660
Range GetRange() const
Definition buffer_view.h:27
static constexpr Color Red()
Definition color.h:272
static Color Random()
Definition color.h:850
static constexpr Color MakeRGBA8(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
Definition color.h:152
static constexpr Color Blue()
Definition color.h:276
static constexpr Color Green()
Definition color.h:274
Scalar degrees
Definition scalar.h:67
static constexpr Matrix MakeOrthographic(TSize< T > size)
Definition matrix.h:633
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition matrix.h:95
static Matrix MakeRotationY(Radians r)
Definition matrix.h:208
static Matrix MakePerspective(Radians fov_y, Scalar aspect_ratio, Scalar z_near, Scalar z_far)
Definition matrix.h:642
static Matrix MakeRotationZ(Radians r)
Definition matrix.h:223
static constexpr Matrix MakeScale(const Vector3 &s)
Definition matrix.h:104
static Matrix MakeRotationX(Radians r)
Definition matrix.h:193
An optional (but highly recommended) utility for creating pipelines from reflected shader information...
static std::optional< PipelineDescriptor > MakeDefaultPipelineDescriptor(const Context &context, const std::vector< Scalar > &constants={})
Create a default pipeline descriptor using the combination reflected shader information....
size_t length
Definition range.h:15
SamplerAddressMode width_address_mode
SamplerAddressMode height_address_mode
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...
#define VALIDATION_LOG
Definition validation.h:91