12#include "impeller/fixtures/array.frag.h"
13#include "impeller/fixtures/array.vert.h"
14#include "impeller/fixtures/box_fade.frag.h"
15#include "impeller/fixtures/box_fade.vert.h"
16#include "impeller/fixtures/colors.frag.h"
17#include "impeller/fixtures/colors.vert.h"
18#include "impeller/fixtures/impeller.frag.h"
19#include "impeller/fixtures/impeller.vert.h"
20#include "impeller/fixtures/inactive_uniforms.frag.h"
21#include "impeller/fixtures/inactive_uniforms.vert.h"
22#include "impeller/fixtures/instanced_draw.frag.h"
23#include "impeller/fixtures/instanced_draw.vert.h"
24#include "impeller/fixtures/mipmaps.frag.h"
25#include "impeller/fixtures/mipmaps.vert.h"
26#include "impeller/fixtures/planet.frag.h"
27#include "impeller/fixtures/planet.vert.h"
28#include "impeller/fixtures/sepia.frag.h"
29#include "impeller/fixtures/sepia.vert.h"
30#include "impeller/fixtures/swizzle.frag.h"
31#include "impeller/fixtures/texture.frag.h"
32#include "impeller/fixtures/texture.vert.h"
41#include "third_party/imgui/imgui.h"
47std::pair<std::shared_ptr<impeller::HostBuffer>,
48 std::shared_ptr<impeller::HostBuffer>>
49createHostBuffers(
const std::shared_ptr<impeller::Context>&
context) {
52 context->GetCapabilities()->GetMinimumUniformAlignment());
53 auto indexes_host_buffer =
54 context->GetCapabilities()->NeedsPartitionedHostBuffer()
57 context->GetCapabilities()->GetMinimumUniformAlignment())
59 return {data_host_buffer, indexes_host_buffer};
70 using VS = BoxFadeVertexShader;
71 using FS = BoxFadeFragmentShader;
75 auto desc = BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*
context);
76 ASSERT_TRUE(desc.has_value());
77 ASSERT_TRUE(InitializePipelineDescriptorForRendering(*desc));
79 desc->ClearStencilAttachments();
80 desc->ClearDepthAttachment();
86 {{100, 100, 0.0}, {0.0, 0.0}},
87 {{800, 100, 0.0}, {1.0, 0.0}},
88 {{800, 800, 0.0}, {1.0, 1.0}},
89 {{100, 100, 0.0}, {0.0, 0.0}},
90 {{800, 800, 0.0}, {1.0, 1.0}},
91 {{100, 800, 0.0}, {0.0, 1.0}},
93 auto bridge = CreateTextureForFixture(
"bay_bridge.jpg");
94 auto boston = CreateTextureForFixture(
"boston.jpg");
95 ASSERT_TRUE(bridge && boston);
99 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(
context);
101 static bool wireframe;
102 if (IsPlaygroundEnabled()) {
103 ImGui::Begin(
"Controls",
nullptr, ImGuiWindowFlags_AlwaysAutoResize);
104 ImGui::Checkbox(
"Wireframe", &wireframe);
109 auto pipeline =
context->GetPipelineLibrary()->GetPipeline(desc).Get();
113 pass.SetCommandLabel(
"Box");
115 pass.SetVertexBuffer(
118 VS::UniformBuffer uniforms;
119 EXPECT_EQ(pass.GetOrthographicTransform(),
123 VS::BindUniformBuffer(pass, data_host_buffer->EmplaceUniform(uniforms));
125 FS::FrameInfo frame_info;
126 frame_info.current_time = GetSecondsElapsed();
127 frame_info.cursor_position = GetCursorPosition();
128 frame_info.window_size.x = GetWindowSize().width;
129 frame_info.window_size.y = GetWindowSize().height;
131 FS::BindFrameInfo(pass, data_host_buffer->EmplaceUniform(frame_info));
132 FS::BindContents1(pass, boston, sampler);
133 FS::BindContents2(pass, bridge, sampler);
135 data_host_buffer->Reset();
136 return pass.Draw().ok();
142 using VS = ColorsVertexShader;
143 using FS = ColorsFragmentShader;
147 ASSERT_TRUE(desc.has_value());
148 ASSERT_TRUE(InitializePipelineDescriptorForRendering(*desc));
154 auto vertex_desc = std::make_shared<VertexDescriptor>();
161 const std::vector<ShaderStageIOSlot> io_slots = {position_slot, color_slot};
162 const std::vector<ShaderStageBufferLayout> layouts = {
165 vertex_desc->RegisterDescriptorSetLayouts(VS::kDescriptorSetLayouts);
166 vertex_desc->RegisterDescriptorSetLayouts(FS::kDescriptorSetLayouts);
167 vertex_desc->SetStageInputs(io_slots, layouts);
168 desc->SetVertexDescriptor(std::move(vertex_desc));
170 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
187 Color::Red(), Color::Yellow(), Color::Green(), Color::Blue(),
188 Color::Green(), Color::Blue(), Color::Red(), Color::Yellow(),
190 uint16_t indices[36] = {
200 auto device_buffer =
context->GetResourceAllocator()->CreateBufferWithCopy(
201 reinterpret_cast<uint8_t*
>(&cube),
sizeof(cube));
204 ASSERT_TRUE(sampler);
207 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(
context);
210 static Scalar distance = 10;
212 if (IsPlaygroundEnabled()) {
213 ImGui::Begin(
"Controls",
nullptr, ImGuiWindowFlags_AlwaysAutoResize);
214 ImGui::SliderFloat(
"Field of view", &fov_y.
degrees, 0, 180);
215 ImGui::SliderFloat(
"Camera distance", &distance, 0, 30);
219 pass.SetCommandLabel(
"Perspective Cube");
222 std::array<BufferView, 2> vertex_buffers = {
224 Range(offsetof(Cube, positions),
sizeof(Cube::positions))),
226 Range(offsetof(Cube, colors),
sizeof(Cube::colors))),
230 device_buffer,
Range(offsetof(Cube, indices),
sizeof(Cube::indices)));
231 pass.SetVertexBuffer(vertex_buffers.data(), vertex_buffers.size());
232 pass.SetElementCount(36);
235 VS::UniformBuffer uniforms;
236 Scalar time = GetSecondsElapsed();
237 euler_angles =
Vector3(0.19 * time, 0.7 * time, 0.43 * time);
245 VS::BindUniformBuffer(pass, data_host_buffer->EmplaceUniform(uniforms));
247 data_host_buffer->Reset();
248 return pass.Draw().ok();
254 using VS = BoxFadeVertexShader;
255 using FS = BoxFadeFragmentShader;
259 auto desc = BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*
context);
260 ASSERT_TRUE(desc.has_value());
261 ASSERT_TRUE(InitializePipelineDescriptorForRendering(*desc));
263 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
264 ASSERT_TRUE(box_pipeline);
270 {{100, 100, 0.0}, {0.0, 0.0}},
271 {{800, 100, 0.0}, {1.0, 0.0}},
272 {{800, 800, 0.0}, {1.0, 1.0}},
273 {{100, 100, 0.0}, {0.0, 0.0}},
274 {{800, 800, 0.0}, {1.0, 1.0}},
275 {{100, 800, 0.0}, {0.0, 1.0}},
279 ASSERT_TRUE(vertex_buffer);
281 auto bridge = CreateTextureForFixture(
"bay_bridge.jpg");
282 auto boston = CreateTextureForFixture(
"boston.jpg");
283 ASSERT_TRUE(bridge && boston);
285 ASSERT_TRUE(sampler);
287 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(
context);
289 for (
size_t i = 0;
i < 1;
i++) {
290 for (
size_t j = 0; j < 1; j++) {
291 pass.SetCommandLabel(
"Box");
292 pass.SetPipeline(box_pipeline);
293 pass.SetVertexBuffer(vertex_buffer);
295 FS::FrameInfo frame_info;
296 frame_info.current_time = GetSecondsElapsed();
297 frame_info.cursor_position = GetCursorPosition();
298 frame_info.window_size.x = GetWindowSize().width;
299 frame_info.window_size.y = GetWindowSize().height;
301 FS::BindFrameInfo(pass, data_host_buffer->EmplaceUniform(frame_info));
302 FS::BindContents1(pass, boston, sampler);
303 FS::BindContents2(pass, bridge, sampler);
305 VS::UniformBuffer uniforms;
306 EXPECT_EQ(pass.GetOrthographicTransform(),
308 uniforms.mvp = pass.GetOrthographicTransform() *
311 VS::BindUniformBuffer(pass, data_host_buffer->EmplaceUniform(uniforms));
312 if (!pass.Draw().ok()) {
318 data_host_buffer->Reset();
325 using VS = BoxFadeVertexShader;
326 using FS = BoxFadeFragmentShader;
331 BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*
context);
333 pipeline_desc->ClearDepthAttachment();
336 ASSERT_TRUE(pipeline_desc.has_value());
338 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
339 ASSERT_TRUE(box_pipeline);
340 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(
context);
345 {{100, 100, 0.0}, {0.0, 0.0}},
346 {{800, 100, 0.0}, {1.0, 0.0}},
347 {{800, 800, 0.0}, {1.0, 1.0}},
348 {{100, 100, 0.0}, {0.0, 0.0}},
349 {{800, 800, 0.0}, {1.0, 1.0}},
350 {{100, 800, 0.0}, {0.0, 1.0}},
354 ASSERT_TRUE(vertex_buffer);
356 auto bridge = CreateTextureForFixture(
"bay_bridge.jpg");
357 auto boston = CreateTextureForFixture(
"boston.jpg");
358 ASSERT_TRUE(bridge && boston);
360 ASSERT_TRUE(sampler);
362 std::shared_ptr<RenderPass> r2t_pass;
363 auto cmd_buffer =
context->CreateCommandBuffer();
364 ASSERT_TRUE(cmd_buffer);
371 ASSERT_NE(pipeline_desc->GetColorAttachmentDescriptor(0u),
nullptr);
372 texture_descriptor.
format =
373 pipeline_desc->GetColorAttachmentDescriptor(0u)->format;
375 texture_descriptor.
size = {400, 400};
380 context->GetResourceAllocator()->CreateTexture(texture_descriptor);
384 color0.
texture->SetLabel(
"r2t_target");
391 stencil_texture_desc.
size = texture_descriptor.
size;
395 context->GetResourceAllocator()->CreateTexture(stencil_texture_desc);
400 r2t_pass = cmd_buffer->CreateRenderPass(r2t_desc);
401 ASSERT_TRUE(r2t_pass && r2t_pass->IsValid());
404 r2t_pass->SetCommandLabel(
"Box");
405 r2t_pass->SetPipeline(box_pipeline);
406 r2t_pass->SetVertexBuffer(vertex_buffer);
408 FS::FrameInfo frame_info;
409 frame_info.current_time = GetSecondsElapsed();
410 frame_info.cursor_position = GetCursorPosition();
411 frame_info.window_size.x = GetWindowSize().width;
412 frame_info.window_size.y = GetWindowSize().height;
414 FS::BindFrameInfo(*r2t_pass, data_host_buffer->EmplaceUniform(frame_info));
415 FS::BindContents1(*r2t_pass, boston, sampler);
416 FS::BindContents2(*r2t_pass, bridge, sampler);
418 VS::UniformBuffer uniforms;
421 VS::BindUniformBuffer(*r2t_pass, data_host_buffer->EmplaceUniform(uniforms));
422 ASSERT_TRUE(r2t_pass->Draw().ok());
423 ASSERT_TRUE(r2t_pass->EncodeCommands());
424 ASSERT_TRUE(
context->FlushCommandBuffers());
434 GTEST_SKIP() <<
"This test's instance-ID mechanism requires OpenGL ES 3.1; "
435 "CanRenderInstancedWithVertexAttributes covers the "
436 "portable instance-rate path.";
438 using VS = InstancedDrawVertexShader;
439 using FS = InstancedDrawFragmentShader;
443 VS::PerVertexData{
Point{10, 10}},
444 VS::PerVertexData{
Point{10, 110}},
445 VS::PerVertexData{
Point{110, 10}},
446 VS::PerVertexData{
Point{10, 110}},
447 VS::PerVertexData{
Point{110, 10}},
448 VS::PerVertexData{
Point{110, 110}},
451 std::shared_ptr<Context>
context = GetContext();
454 ASSERT_TRUE(desc.has_value());
455 ASSERT_TRUE(InitializePipelineDescriptorForRendering(*desc));
456 auto pipeline = GetContext()->GetPipelineLibrary()->GetPipeline(desc).Get();
459 static constexpr size_t kInstancesCount = 5u;
460 VS::InstanceInfo<kInstancesCount> instances;
461 for (
size_t i = 0;
i < kInstancesCount;
i++) {
465 auto [data_host_buffer, indexes_host_buffer] =
466 createHostBuffers(GetContext());
467 ASSERT_TRUE(OpenPlaygroundHere([&](
RenderPass& pass) ->
bool {
471 VS::FrameInfo frame_info;
476 VS::BindFrameInfo(pass, data_host_buffer->EmplaceUniform(frame_info));
477 VS::BindInstanceInfo(pass,
478 data_host_buffer->EmplaceStorageBuffer(instances));
485 data_host_buffer->Reset();
494 GTEST_SKIP() <<
"Mipmap test shader not supported on GLES or Vulkan.";
499 using VS = MipmapsVertexShader;
500 using FS = MipmapsFragmentShader;
502 ASSERT_TRUE(desc.has_value());
503 ASSERT_TRUE(InitializePipelineDescriptorForRendering(*desc));
504 auto mipmaps_pipeline =
505 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
506 ASSERT_TRUE(mipmaps_pipeline);
511 texture_desc.
size = {800, 600};
514 auto texture =
context->GetResourceAllocator()->CreateTexture(texture_desc);
517 auto bridge = CreateTextureForFixture(
"bay_bridge.jpg");
518 auto boston = CreateTextureForFixture(
"boston.jpg");
519 ASSERT_TRUE(bridge && boston);
521 ASSERT_TRUE(sampler);
528 {{0, 0}, {0.0, 0.0}},
529 {{
size.x, 0}, {1.0, 0.0}},
531 {{0, 0}, {0.0, 0.0}},
533 {{0,
size.y}, {0.0, 1.0}},
537 ASSERT_TRUE(vertex_buffer);
539 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(
context);
545 buffer->SetLabel(
"Playground Command Buffer");
548 auto pass =
buffer->CreateBlitPass();
552 pass->SetLabel(
"Playground Blit Pass");
559 std::optional<IRect> blit_bounds =
561 pass->AddCopy(bridge,
texture, blit_bounds);
563 if (!pass->EncodeCommands()) {
569 auto pass =
buffer->CreateRenderPass(render_target);
573 pass->SetLabel(
"Playground Render Pass");
575 pass->SetCommandLabel(
"Image");
576 pass->SetPipeline(mipmaps_pipeline);
577 pass->SetVertexBuffer(vertex_buffer);
579 VS::FrameInfo frame_info;
580 EXPECT_EQ(pass->GetOrthographicTransform(),
582 frame_info.mvp = pass->GetOrthographicTransform() *
584 VS::BindFrameInfo(*pass, data_host_buffer->EmplaceUniform(frame_info));
586 FS::FragInfo frag_info;
588 FS::BindFragInfo(*pass, data_host_buffer->EmplaceUniform(frag_info));
590 auto sampler =
context->GetSamplerLibrary()->GetSampler({});
591 FS::BindTex(*pass,
texture, sampler);
595 pass->EncodeCommands();
598 if (!
context->GetCommandQueue()->Submit({buffer}).ok()) {
601 data_host_buffer->Reset();
610 GTEST_SKIP() <<
"Mipmap test shader not supported on GLES.";
615 using VS = MipmapsVertexShader;
616 using FS = MipmapsFragmentShader;
618 ASSERT_TRUE(desc.has_value());
619 ASSERT_TRUE(InitializePipelineDescriptorForRendering(*desc));
620 auto mipmaps_pipeline =
621 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
622 ASSERT_TRUE(mipmaps_pipeline);
624 auto bridge = CreateTextureForFixture(
"bay_bridge.jpg");
625 auto boston = CreateTextureForFixture(
"boston.jpg");
626 ASSERT_TRUE(bridge && boston);
628 ASSERT_TRUE(sampler);
633 texture_desc.
size = bridge->GetTextureDescriptor().size;
639 device_buffer_desc.
size =
640 bridge->GetTextureDescriptor().GetByteSizeOfBaseMipLevel();
642 context->GetResourceAllocator()->CreateBuffer(device_buffer_desc);
649 {{0, 0}, {0.0, 0.0}},
650 {{
size.x, 0}, {1.0, 0.0}},
652 {{0, 0}, {0.0, 0.0}},
654 {{0,
size.y}, {0.0, 1.0}},
658 ASSERT_TRUE(vertex_buffer);
660 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(
context);
667 buffer->SetLabel(
"Playground Command Buffer");
668 auto pass =
buffer->CreateBlitPass();
672 pass->SetLabel(
"Playground Blit Pass");
675 pass->AddCopy(bridge, device_buffer);
676 pass->EncodeCommands();
688 buffer->SetLabel(
"Playground Command Buffer");
690 auto pass =
buffer->CreateRenderPass(render_target);
694 pass->SetLabel(
"Playground Render Pass");
696 pass->SetCommandLabel(
"Image");
697 pass->SetPipeline(mipmaps_pipeline);
698 pass->SetVertexBuffer(vertex_buffer);
700 VS::FrameInfo frame_info;
701 EXPECT_EQ(pass->GetOrthographicTransform(),
703 frame_info.mvp = pass->GetOrthographicTransform() *
705 VS::BindFrameInfo(*pass, data_host_buffer->EmplaceUniform(frame_info));
707 FS::FragInfo frag_info;
709 FS::BindFragInfo(*pass, data_host_buffer->EmplaceUniform(frag_info));
712 context->GetSamplerLibrary()->GetSampler({});
715 context->GetResourceAllocator()->CreateTexture(texture_desc);
716 if (!
texture->SetContents(device_buffer->OnGetContents(),
717 buffer_view.GetRange().length)) {
721 FS::BindTex(*pass,
texture, sampler);
725 pass->EncodeCommands();
726 if (!
context->GetCommandQueue()->Submit({buffer}).ok()) {
730 data_host_buffer->Reset();
739 GTEST_SKIP() <<
"Mipmap test shader not supported on GLES.";
744 using VS = MipmapsVertexShader;
745 using FS = MipmapsFragmentShader;
747 ASSERT_TRUE(desc.has_value());
748 ASSERT_TRUE(InitializePipelineDescriptorForRendering(*desc));
749 auto mipmaps_pipeline =
750 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
751 ASSERT_TRUE(mipmaps_pipeline);
753 auto boston = CreateTextureForFixture(
"boston.jpg",
true);
761 {{0, 0}, {0.0, 0.0}},
762 {{
size.x, 0}, {1.0, 0.0}},
764 {{0, 0}, {0.0, 0.0}},
766 {{0,
size.y}, {0.0, 1.0}},
770 ASSERT_TRUE(vertex_buffer);
772 bool first_frame =
true;
773 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(
context);
775 const char* mip_filter_names[] = {
"Base",
"Nearest",
"Linear"};
778 const char* min_filter_names[] = {
"Nearest",
"Linear"};
783 static int selected_mip_filter = 1;
784 static int selected_min_filter = 0;
785 static float lod = 4.5;
787 if (IsPlaygroundEnabled()) {
788 ImGui::Begin(
"Controls",
nullptr, ImGuiWindowFlags_AlwaysAutoResize);
789 ImGui::Combo(
"Mip filter", &selected_mip_filter, mip_filter_names,
790 sizeof(mip_filter_names) /
sizeof(
char*));
791 ImGui::Combo(
"Min filter", &selected_min_filter, min_filter_names,
792 sizeof(min_filter_names) /
sizeof(
char*));
793 ImGui::SliderFloat(
"LOD", &lod, 0, boston->GetMipCount() - 1);
801 buffer->SetLabel(
"Playground Command Buffer");
804 auto pass =
buffer->CreateBlitPass();
808 pass->SetLabel(
"Playground Blit Pass");
810 pass->GenerateMipmap(boston,
"Boston Mipmap");
812 pass->EncodeCommands();
818 auto pass =
buffer->CreateRenderPass(render_target);
822 pass->SetLabel(
"Playground Render Pass");
824 pass->SetCommandLabel(
"Image LOD");
825 pass->SetPipeline(mipmaps_pipeline);
826 pass->SetVertexBuffer(vertex_buffer);
828 VS::FrameInfo frame_info;
829 EXPECT_EQ(pass->GetOrthographicTransform(),
831 frame_info.mvp = pass->GetOrthographicTransform() *
833 VS::BindFrameInfo(*pass, data_host_buffer->EmplaceUniform(frame_info));
835 FS::FragInfo frag_info;
837 FS::BindFragInfo(*pass, data_host_buffer->EmplaceUniform(frag_info));
840 sampler_desc.
mip_filter = mip_filters[selected_mip_filter];
841 sampler_desc.
min_filter = min_filters[selected_min_filter];
843 context->GetSamplerLibrary()->GetSampler(sampler_desc);
844 FS::BindTex(*pass, boston, sampler);
848 pass->EncodeCommands();
851 if (!
context->GetCommandQueue()->Submit({buffer}).ok()) {
854 data_host_buffer->Reset();
861 using VS = ImpellerVertexShader;
862 using FS = ImpellerFragmentShader;
865 auto pipeline_descriptor =
867 ASSERT_TRUE(pipeline_descriptor.has_value());
868 ASSERT_TRUE(InitializePipelineDescriptorForRendering(*pipeline_descriptor));
870 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
873 auto blue_noise = CreateTextureForFixture(
"blue_noise.png");
878 context->GetSamplerLibrary()->GetSampler(noise_sampler_desc);
880 auto cube_map = CreateTextureCubeForFixture(
881 {
"table_mountain_px.png",
"table_mountain_nx.png",
882 "table_mountain_py.png",
"table_mountain_ny.png",
883 "table_mountain_pz.png",
"table_mountain_nz.png"});
885 context->GetSamplerLibrary()->GetSampler({});
887 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(
context);
889 auto size = pass.GetRenderTargetSize();
892 pass.SetCommandLabel(
"Impeller SDF scene");
900 pass.SetVertexBuffer(
903 VS::FrameInfo frame_info;
905 frame_info.mvp = pass.GetOrthographicTransform();
906 VS::BindFrameInfo(pass, data_host_buffer->EmplaceUniform(frame_info));
908 FS::FragInfo fs_uniform;
910 fs_uniform.time = GetSecondsElapsed();
911 FS::BindFragInfo(pass, data_host_buffer->EmplaceUniform(fs_uniform));
912 FS::BindBlueNoise(pass, blue_noise, noise_sampler);
913 FS::BindCubeMap(pass, cube_map, cube_map_sampler);
916 data_host_buffer->Reset();
923 using VS = PlanetVertexShader;
924 using FS = PlanetFragmentShader;
927 auto pipeline_descriptor =
929 ASSERT_TRUE(pipeline_descriptor.has_value());
930 ASSERT_TRUE(InitializePipelineDescriptorForRendering(*pipeline_descriptor));
932 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
935 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(
context);
937 static Scalar speed = 0.1;
938 static Scalar planet_size = 550.0;
939 static bool show_normals =
false;
940 static bool show_noise =
false;
941 static Scalar seed_value = 42.0;
943 auto size = pass.GetRenderTargetSize();
945 if (IsPlaygroundEnabled()) {
946 ImGui::Begin(
"Controls",
nullptr, ImGuiWindowFlags_AlwaysAutoResize);
947 ImGui::SliderFloat(
"Speed", &speed, 0.0, 10.0);
948 ImGui::SliderFloat(
"Planet Size", &planet_size, 0.1, 1000);
949 ImGui::Checkbox(
"Show Normals", &show_normals);
950 ImGui::Checkbox(
"Show Noise", &show_noise);
951 ImGui::InputFloat(
"Seed Value", &seed_value);
956 pass.SetCommandLabel(
"Planet scene");
964 pass.SetVertexBuffer(
967 VS::FrameInfo frame_info;
969 frame_info.mvp = pass.GetOrthographicTransform();
970 VS::BindFrameInfo(pass, data_host_buffer->EmplaceUniform(frame_info));
972 FS::FragInfo fs_uniform;
974 fs_uniform.time = GetSecondsElapsed();
975 fs_uniform.speed = speed;
976 fs_uniform.planet_size = planet_size;
977 fs_uniform.show_normals = show_normals ? 1.0 : 0.0;
978 fs_uniform.show_noise = show_noise ? 1.0 : 0.0;
979 fs_uniform.seed_value = seed_value;
980 FS::BindFragInfo(pass, data_host_buffer->EmplaceUniform(fs_uniform));
983 data_host_buffer->Reset();
990 using VS = ArrayVertexShader;
991 using FS = ArrayFragmentShader;
994 auto pipeline_descriptor =
996 ASSERT_TRUE(pipeline_descriptor.has_value());
997 ASSERT_TRUE(InitializePipelineDescriptorForRendering(*pipeline_descriptor));
999 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
1002 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(
context);
1004 auto size = pass.GetRenderTargetSize();
1007 pass.SetCommandLabel(
"Google Dots");
1015 pass.SetVertexBuffer(
1018 VS::FrameInfo frame_info;
1022 VS::BindFrameInfo(pass, data_host_buffer->EmplaceUniform(frame_info));
1024 auto time = GetSecondsElapsed();
1025 auto y_pos = [&time](
float x) {
1026 return 400 + 10 * std::cos(time * 5 +
x / 6);
1029 FS::FragInfo fs_uniform = {
1030 .circle_positions = {
Point(430, y_pos(0)),
Point(480, y_pos(1)),
1037 FS::BindFragInfo(pass, data_host_buffer->EmplaceUniform(fs_uniform));
1040 data_host_buffer->Reset();
1047 using VS = InactiveUniformsVertexShader;
1048 using FS = InactiveUniformsFragmentShader;
1051 auto pipeline_descriptor =
1053 ASSERT_TRUE(pipeline_descriptor.has_value());
1054 ASSERT_TRUE(InitializePipelineDescriptorForRendering(*pipeline_descriptor));
1056 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
1059 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(
context);
1061 auto size = pass.GetRenderTargetSize();
1064 pass.SetCommandLabel(
"Inactive Uniform");
1073 pass.SetVertexBuffer(
1076 VS::FrameInfo frame_info;
1080 VS::BindFrameInfo(pass, data_host_buffer->EmplaceUniform(frame_info));
1082 FS::FragInfo fs_uniform = {.unused_color =
Color::Red(),
1084 FS::BindFragInfo(pass, data_host_buffer->EmplaceUniform(fs_uniform));
1087 data_host_buffer->Reset();
1094 using VS = BoxFadeVertexShader;
1104 using VS = BoxFadeVertexShader;
1113 using VS = BoxFadeVertexShader;
1117 {{100, 100, 0.0}, {0.0, 0.0}},
1118 {{800, 100, 0.0}, {1.0, 0.0}},
1119 {{800, 800, 0.0}, {1.0, 1.0}},
1120 {{100, 800, 0.0}, {0.0, 1.0}},
1136 labels_.push_back(
"Never");
1138 labels_.push_back(
"Always");
1140 labels_.push_back(
"Less");
1142 labels_.push_back(
"Equal");
1144 labels_.push_back(
"LessEqual");
1146 labels_.push_back(
"Greater");
1148 labels_.push_back(
"NotEqual");
1150 labels_.push_back(
"GreaterEqual");
1152 assert(labels_.size() == functions_.size());
1155 const char*
const*
labels()
const {
return &labels_[0]; }
1157 int size()
const {
return labels_.size(); }
1160 for (
size_t i = 0;
i < functions_.size();
i++) {
1161 if (functions_[
i] == func) {
1172 std::vector<const char*> labels_;
1173 std::vector<CompareFunction> functions_;
1182 using VS = BoxFadeVertexShader;
1183 using FS = BoxFadeFragmentShader;
1187 auto desc = BoxFadePipelineBuilder::MakeDefaultPipelineDescriptor(*
context);
1188 ASSERT_TRUE(desc.has_value());
1194 {{100, 100, 0.0}, {0.0, 0.0}},
1195 {{800, 100, 0.0}, {1.0, 0.0}},
1196 {{800, 800, 0.0}, {1.0, 1.0}},
1197 {{100, 100, 0.0}, {0.0, 0.0}},
1198 {{800, 800, 0.0}, {1.0, 1.0}},
1199 {{100, 800, 0.0}, {0.0, 1.0}},
1201 auto vertex_buffer =
1203 ASSERT_TRUE(vertex_buffer);
1206 desc->SetStencilAttachmentDescriptors(std::nullopt);
1208 auto bridge = CreateTextureForFixture(
"bay_bridge.jpg");
1209 auto boston = CreateTextureForFixture(
"boston.jpg");
1210 ASSERT_TRUE(bridge && boston);
1212 ASSERT_TRUE(sampler);
1214 static bool mirror =
false;
1215 static int stencil_reference_write = 0xFF;
1216 static int stencil_reference_read = 0x1;
1217 std::vector<uint8_t> stencil_contents;
1218 static int last_stencil_contents_reference_value = 0;
1219 static int current_front_compare =
1221 static int current_back_compare =
1224 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(
context);
1230 buffer->SetLabel(
"Playground Command Buffer");
1238 render_target.SetupDepthStencilAttachments(
1240 render_target.GetRenderTargetSize(),
true,
"stencil", stencil_config);
1242 const auto target_width = render_target.GetRenderTargetSize().width;
1243 const auto target_height = render_target.GetRenderTargetSize().height;
1244 const size_t target_size = target_width * target_height;
1245 if (stencil_contents.size() != target_size ||
1246 last_stencil_contents_reference_value != stencil_reference_write) {
1247 stencil_contents.resize(target_size);
1248 last_stencil_contents_reference_value = stencil_reference_write;
1249 for (
int y = 0;
y < target_height;
y++) {
1250 for (
int x = 0;
x < target_width;
x++) {
1251 const auto index =
y * target_width +
x;
1252 const auto kCheckSize = 64;
1254 (((
y / kCheckSize) + (
x / kCheckSize)) % 2 == 0) *
1255 stencil_reference_write;
1256 stencil_contents[index] =
value;
1260 if (!render_target.GetStencilAttachment()->texture->SetContents(
1261 stencil_contents.data(), stencil_contents.size(), 0,
false)) {
1262 VALIDATION_LOG <<
"Could not upload stencil contents to device memory";
1265 auto pass =
buffer->CreateRenderPass(render_target);
1269 pass->SetLabel(
"Stencil Buffer");
1270 if (IsPlaygroundEnabled()) {
1271 ImGui::Begin(
"Controls",
nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1272 ImGui::SliderInt(
"Stencil Write Value", &stencil_reference_write, 0,
1274 ImGui::SliderInt(
"Stencil Compare Value", &stencil_reference_read, 0,
1276 ImGui::Checkbox(
"Back face mode", &mirror);
1277 ImGui::ListBox(
"Front face compare function", ¤t_front_compare,
1280 ImGui::ListBox(
"Back face compare function", ¤t_back_compare,
1292 desc->SetStencilAttachmentDescriptors(front, back);
1293 auto pipeline =
context->GetPipelineLibrary()->GetPipeline(desc).Get();
1297 pass->SetCommandLabel(
"Box");
1299 pass->SetStencilReference(stencil_reference_read);
1300 pass->SetVertexBuffer(vertex_buffer);
1302 VS::UniformBuffer uniforms;
1303 EXPECT_EQ(pass->GetOrthographicTransform(),
1305 uniforms.mvp = pass->GetOrthographicTransform() *
1310 VS::BindUniformBuffer(*pass, data_host_buffer->EmplaceUniform(uniforms));
1312 FS::FrameInfo frame_info;
1313 frame_info.current_time = GetSecondsElapsed();
1314 frame_info.cursor_position = GetCursorPosition();
1315 frame_info.window_size.x = GetWindowSize().width;
1316 frame_info.window_size.y = GetWindowSize().height;
1318 FS::BindFrameInfo(*pass, data_host_buffer->EmplaceUniform(frame_info));
1319 FS::BindContents1(*pass, boston, sampler);
1320 FS::BindContents2(*pass, bridge, sampler);
1321 if (!pass->Draw().ok()) {
1324 pass->EncodeCommands();
1327 if (!
context->GetCommandQueue()->Submit({buffer}).ok()) {
1330 data_host_buffer->Reset();
1335 GTEST_SKIP() <<
"See: https://github.com/flutter/flutter/issues/188884";
1342 auto cmd_buffer =
context->CreateCommandBuffer();
1343 auto render_target_cache = std::make_shared<RenderTargetAllocator>(
1344 GetContext()->GetResourceAllocator());
1346 auto render_target = render_target_cache->CreateOffscreen(
1348 auto render_pass = cmd_buffer->CreateRenderPass(render_target);
1350 EXPECT_EQ(
render_pass->GetSampleCount(), render_target.GetSampleCount());
1351 EXPECT_EQ(
render_pass->GetRenderTargetPixelFormat(),
1352 render_target.GetRenderTargetPixelFormat());
1354 render_target.GetStencilAttachment().has_value());
1356 render_target.GetRenderTargetSize());
1361 RenderTargetCreateOffscreenMSAASetsDefaultDepthStencilFormat) {
1363 auto render_target_cache = std::make_shared<RenderTargetAllocator>(
1364 GetContext()->GetResourceAllocator());
1366 RenderTarget render_target = render_target_cache->CreateOffscreenMSAA(
1369 ->texture->GetTextureDescriptor()
1371 GetContext()->GetCapabilities()->GetDefaultDepthStencilFormat());
1374template <
class VertexShader,
class FragmentShader>
1377 const std::shared_ptr<Context>&
context) {
1379 auto pipeline_desc =
1380 TexturePipelineBuilder::MakeDefaultPipelineDescriptor(*
context);
1381 if (!pipeline_desc.has_value()) {
1388 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
1397 using TextureVS = TextureVertexShader;
1398 using TextureFS = TextureFragmentShader;
1400 using SepiaVS = SepiaVertexShader;
1401 using SepiaFS = SepiaFragmentShader;
1406 if (!
context->GetCapabilities()->SupportsFramebufferFetch()) {
1407 GTEST_SKIP() <<
"This test uses framebuffer fetch and the backend doesn't "
1413 auto texture_pipeline =
1414 CreateDefaultPipeline<TextureVS, TextureFS>(
this,
context);
1415 auto sepia_pipeline = CreateDefaultPipeline<SepiaVS, SepiaFS>(
this,
context);
1417 ASSERT_TRUE(texture_pipeline);
1418 ASSERT_TRUE(sepia_pipeline);
1423 {{100, 100, 0.0}, {0.0, 0.0}},
1424 {{800, 100, 0.0}, {1.0, 0.0}},
1425 {{800, 800, 0.0}, {1.0, 1.0}},
1426 {{100, 100, 0.0}, {0.0, 0.0}},
1427 {{800, 800, 0.0}, {1.0, 1.0}},
1428 {{100, 800, 0.0}, {0.0, 1.0}},
1441 auto boston = CreateTextureForFixture(
"boston.jpg");
1442 ASSERT_TRUE(boston);
1444 const auto& sampler =
context->GetSamplerLibrary()->GetSampler({});
1445 ASSERT_TRUE(sampler);
1449 context->GetCapabilities()->GetMinimumUniformAlignment());
1453 pass.SetPipeline(texture_pipeline);
1455 *
context->GetResourceAllocator()));
1456 TextureVS::UniformBuffer uniforms;
1459 TextureVS::BindUniformBuffer(pass,
buffer->EmplaceUniform(uniforms));
1460 TextureFS::BindTextureContents(pass, boston, sampler);
1461 if (!pass.Draw().ok()) {
1468 pass.SetPipeline(sepia_pipeline);
1470 *
context->GetResourceAllocator()));
1471 SepiaVS::UniformBuffer uniforms;
1474 SepiaVS::BindUniformBuffer(pass,
buffer->EmplaceUniform(uniforms));
1475 if (!pass.Draw().ok()) {
1486 switch (GetBackend()) {
1493 GTEST_SKIP() <<
"Platform is crashing in CI on this example "
1494 <<
"(see https://github.com/flutter/flutter/issues/189287).";
1497 using TextureVS = TextureVertexShader;
1498 using TextureFS = TextureFragmentShader;
1500 using SwizzleVS = SepiaVertexShader;
1501 using SwizzleFS = SwizzleFragmentShader;
1503 using SepiaVS = SepiaVertexShader;
1504 using SepiaFS = SepiaFragmentShader;
1509 if (!
context->GetCapabilities()->SupportsFramebufferFetch()) {
1510 GTEST_SKIP() <<
"This test uses framebuffer fetch and the backend doesn't "
1516 auto texture_pipeline =
1517 CreateDefaultPipeline<TextureVS, TextureFS>(
this,
context);
1518 auto swizzle_pipeline =
1519 CreateDefaultPipeline<SwizzleVS, SwizzleFS>(
this,
context);
1520 auto sepia_pipeline = CreateDefaultPipeline<SepiaVS, SepiaFS>(
this,
context);
1522 ASSERT_TRUE(texture_pipeline);
1523 ASSERT_TRUE(swizzle_pipeline);
1524 ASSERT_TRUE(sepia_pipeline);
1529 {{100, 100, 0.0}, {0.0, 0.0}},
1530 {{800, 100, 0.0}, {1.0, 0.0}},
1531 {{800, 800, 0.0}, {1.0, 1.0}},
1532 {{100, 100, 0.0}, {0.0, 0.0}},
1533 {{800, 800, 0.0}, {1.0, 1.0}},
1534 {{100, 800, 0.0}, {0.0, 1.0}},
1547 auto boston = CreateTextureForFixture(
"boston.jpg");
1548 ASSERT_TRUE(boston);
1550 const auto& sampler =
context->GetSamplerLibrary()->GetSampler({});
1551 ASSERT_TRUE(sampler);
1555 context->GetCapabilities()->GetMinimumUniformAlignment());
1559 pass.SetPipeline(texture_pipeline);
1561 *
context->GetResourceAllocator()));
1562 TextureVS::UniformBuffer uniforms;
1565 TextureVS::BindUniformBuffer(pass, data_buffer->EmplaceUniform(uniforms));
1566 TextureFS::BindTextureContents(pass, boston, sampler);
1567 if (!pass.Draw().ok()) {
1574 pass.SetPipeline(sepia_pipeline);
1576 *
context->GetResourceAllocator()));
1577 SepiaVS::UniformBuffer uniforms;
1580 SepiaVS::BindUniformBuffer(pass, data_buffer->EmplaceUniform(uniforms));
1581 if (!pass.Draw().ok()) {
1588 pass.SetPipeline(swizzle_pipeline);
1590 *
context->GetResourceAllocator()));
1591 SwizzleVS::UniformBuffer uniforms;
1594 SwizzleVS::BindUniformBuffer(pass, data_buffer->EmplaceUniform(uniforms));
1595 if (!pass.Draw().ok()) {
1606 using FS = BoxFadeFragmentShader;
1616 EXPECT_FALSE(FS::BindContents2(*pass,
nullptr, sampler));
1630 desc.
size = {100, 100};
1632 auto texture =
context->GetResourceAllocator()->CreateTexture(desc);
1646 ASSERT_TRUE(pass && pass->IsValid());
1647 pass->EncodeCommands();
1648 EXPECT_TRUE(
context->GetCommandQueue()->Submit({buffer}).ok());
1657 GTEST_SKIP() <<
"Rendering to non-zero mip levels is gated on a GLES "
1658 "capability; covered by the Metal and Vulkan backends.";
1666 desc.
size = {100, 100};
1669 auto texture =
context->GetResourceAllocator()->CreateTexture(desc);
1681 EXPECT_EQ(
target.GetRenderTargetSize(),
ISize(50, 50));
1685 ASSERT_TRUE(pass && pass->IsValid());
1686 pass->EncodeCommands();
1687 EXPECT_TRUE(
context->GetCommandQueue()->Submit({buffer}).ok());
1698 desc.
size = {100, 100};
1701 auto texture =
context->GetResourceAllocator()->CreateTexture(desc);
1708 EXPECT_TRUE(color0.
IsValid());
1714 EXPECT_FALSE(color0.
IsValid());
1718 EXPECT_FALSE(color0.
IsValid());
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::shared_ptr< const GpuSubmissionTracker > submission_tracker=nullptr)
std::function< bool(RenderTarget &render_target)> RenderCallback
bool InitializePipelineDescriptorForRendering(PipelineDescriptor &desc) const
Initializes the provided |PipelineDescriptor| with appropriate default values to match the conditions...
Render passes encode render commands directed as one specific render target into an underlying comman...
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...
RenderTarget & SetColorAttachment(const ColorAttachment &attachment, size_t index)
RenderTarget & SetStencilAttachment(std::optional< StencilAttachment > attachment)
const std::optional< DepthAttachment > & GetDepthAttachment() const
size_t GetVertexCount() const
size_t GetIndexCount() 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.
CompareFunction FunctionOf(int index) const
const char *const * labels() const
int IndexOf(CompareFunction func) const
FlutterDesktopBinaryReply callback
#define FML_UNREACHABLE()
std::shared_ptr< ImpellerAllocator > allocator
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
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
PlaygroundTest RendererTest
static const CompareFunctionUIData & CompareFunctionUI()
TEST_P(AiksTest, DrawAtlasNoColor)
@ kNone
Does not use the index buffer.
GlyphAtlasPipeline::VertexShader VS
@ 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.
@ 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.
GlyphAtlasPipeline::FragmentShader FS
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 (...
@ kNearest
Select nearest to the sample point. Most widely supported.
#define INSTANTIATE_PLAYGROUND_SUITE(playground)
std::shared_ptr< ContextGLES > context
std::shared_ptr< RenderPass > render_pass
std::shared_ptr< PipelineGLES > pipeline
std::shared_ptr< CommandBuffer > command_buffer
std::shared_ptr< Texture > texture
static constexpr Color Red()
static constexpr Color MakeRGBA8(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
static constexpr Color Green()
static constexpr Matrix MakeOrthographic(TSize< T > size)
static constexpr Matrix MakeTranslation(const Vector3 &t)
static Matrix MakeRotationY(Radians r)
static Matrix MakePerspective(Radians fov_y, Scalar aspect_ratio, Scalar z_near, Scalar z_far)
static Matrix MakeRotationZ(Radians r)
static constexpr Matrix MakeScale(const Vector3 &s)
static Matrix MakeRotationX(Radians r)
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....
SamplerAddressMode width_address_mode
SamplerAddressMode height_address_mode
CompareFunction stencil_compare
constexpr std::optional< TRect > Intersection(const TRect &o) const
static constexpr TRect MakeSize(const TSize< U > &size)
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...