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());
78 desc->SetStencilAttachmentDescriptors(std::nullopt);
84 {{100, 100, 0.0}, {0.0, 0.0}},
85 {{800, 100, 0.0}, {1.0, 0.0}},
86 {{800, 800, 0.0}, {1.0, 1.0}},
87 {{100, 100, 0.0}, {0.0, 0.0}},
88 {{800, 800, 0.0}, {1.0, 1.0}},
89 {{100, 800, 0.0}, {0.0, 1.0}},
91 auto bridge = CreateTextureForFixture(
"bay_bridge.jpg");
92 auto boston = CreateTextureForFixture(
"boston.jpg");
93 ASSERT_TRUE(bridge && boston);
97 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(
context);
99 ImGui::Begin(
"Controls",
nullptr, ImGuiWindowFlags_AlwaysAutoResize);
100 static bool wireframe;
101 ImGui::Checkbox(
"Wireframe", &wireframe);
105 auto pipeline =
context->GetPipelineLibrary()->GetPipeline(desc).Get();
109 pass.SetCommandLabel(
"Box");
111 pass.SetVertexBuffer(
114 VS::UniformBuffer uniforms;
115 EXPECT_EQ(pass.GetOrthographicTransform(),
119 VS::BindUniformBuffer(pass, data_host_buffer->EmplaceUniform(uniforms));
121 FS::FrameInfo frame_info;
122 frame_info.current_time = GetSecondsElapsed();
123 frame_info.cursor_position = GetCursorPosition();
124 frame_info.window_size.x = GetWindowSize().width;
125 frame_info.window_size.y = GetWindowSize().height;
127 FS::BindFrameInfo(pass, data_host_buffer->EmplaceUniform(frame_info));
128 FS::BindContents1(pass, boston, sampler);
129 FS::BindContents2(pass, bridge, sampler);
131 data_host_buffer->Reset();
132 return pass.Draw().ok();
138 using VS = ColorsVertexShader;
139 using FS = ColorsFragmentShader;
143 ASSERT_TRUE(desc.has_value());
147 desc->ClearStencilAttachments();
151 auto vertex_desc = std::make_shared<VertexDescriptor>();
158 const std::vector<ShaderStageIOSlot> io_slots = {position_slot, color_slot};
159 const std::vector<ShaderStageBufferLayout> layouts = {
162 vertex_desc->RegisterDescriptorSetLayouts(VS::kDescriptorSetLayouts);
163 vertex_desc->RegisterDescriptorSetLayouts(FS::kDescriptorSetLayouts);
164 vertex_desc->SetStageInputs(io_slots, layouts);
165 desc->SetVertexDescriptor(std::move(vertex_desc));
167 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
184 Color::Red(), Color::Yellow(), Color::Green(), Color::Blue(),
185 Color::Green(), Color::Blue(), Color::Red(), Color::Yellow(),
187 uint16_t indices[36] = {
197 auto device_buffer =
context->GetResourceAllocator()->CreateBufferWithCopy(
198 reinterpret_cast<uint8_t*
>(&cube),
sizeof(cube));
201 ASSERT_TRUE(sampler);
204 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(
context);
207 static Scalar distance = 10;
209 ImGui::Begin(
"Controls",
nullptr, ImGuiWindowFlags_AlwaysAutoResize);
210 ImGui::SliderFloat(
"Field of view", &fov_y.
degrees, 0, 180);
211 ImGui::SliderFloat(
"Camera distance", &distance, 0, 30);
214 pass.SetCommandLabel(
"Perspective Cube");
217 std::array<BufferView, 2> vertex_buffers = {
219 Range(offsetof(Cube, positions),
sizeof(Cube::positions))),
221 Range(offsetof(Cube, colors),
sizeof(Cube::colors))),
225 device_buffer,
Range(offsetof(Cube, indices),
sizeof(Cube::indices)));
226 pass.SetVertexBuffer(vertex_buffers.data(), vertex_buffers.size());
227 pass.SetElementCount(36);
230 VS::UniformBuffer uniforms;
231 Scalar time = GetSecondsElapsed();
232 euler_angles =
Vector3(0.19 * time, 0.7 * time, 0.43 * time);
240 VS::BindUniformBuffer(pass, data_host_buffer->EmplaceUniform(uniforms));
242 data_host_buffer->Reset();
243 return pass.Draw().ok();
249 using VS = BoxFadeVertexShader;
250 using FS = BoxFadeFragmentShader;
254 auto desc = BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*
context);
255 ASSERT_TRUE(desc.has_value());
257 desc->SetStencilAttachmentDescriptors(std::nullopt);
259 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
260 ASSERT_TRUE(box_pipeline);
266 {{100, 100, 0.0}, {0.0, 0.0}},
267 {{800, 100, 0.0}, {1.0, 0.0}},
268 {{800, 800, 0.0}, {1.0, 1.0}},
269 {{100, 100, 0.0}, {0.0, 0.0}},
270 {{800, 800, 0.0}, {1.0, 1.0}},
271 {{100, 800, 0.0}, {0.0, 1.0}},
275 ASSERT_TRUE(vertex_buffer);
277 auto bridge = CreateTextureForFixture(
"bay_bridge.jpg");
278 auto boston = CreateTextureForFixture(
"boston.jpg");
279 ASSERT_TRUE(bridge && boston);
281 ASSERT_TRUE(sampler);
283 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(
context);
285 for (
size_t i = 0;
i < 1;
i++) {
286 for (
size_t j = 0; j < 1; j++) {
287 pass.SetCommandLabel(
"Box");
288 pass.SetPipeline(box_pipeline);
289 pass.SetVertexBuffer(vertex_buffer);
291 FS::FrameInfo frame_info;
292 frame_info.current_time = GetSecondsElapsed();
293 frame_info.cursor_position = GetCursorPosition();
294 frame_info.window_size.x = GetWindowSize().width;
295 frame_info.window_size.y = GetWindowSize().height;
297 FS::BindFrameInfo(pass, data_host_buffer->EmplaceUniform(frame_info));
298 FS::BindContents1(pass, boston, sampler);
299 FS::BindContents2(pass, bridge, sampler);
301 VS::UniformBuffer uniforms;
302 EXPECT_EQ(pass.GetOrthographicTransform(),
304 uniforms.mvp = pass.GetOrthographicTransform() *
307 VS::BindUniformBuffer(pass, data_host_buffer->EmplaceUniform(uniforms));
308 if (!pass.Draw().ok()) {
314 data_host_buffer->Reset();
321 using VS = BoxFadeVertexShader;
322 using FS = BoxFadeFragmentShader;
327 BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*
context);
329 pipeline_desc->ClearDepthAttachment();
332 ASSERT_TRUE(pipeline_desc.has_value());
334 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
335 ASSERT_TRUE(box_pipeline);
336 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(
context);
341 {{100, 100, 0.0}, {0.0, 0.0}},
342 {{800, 100, 0.0}, {1.0, 0.0}},
343 {{800, 800, 0.0}, {1.0, 1.0}},
344 {{100, 100, 0.0}, {0.0, 0.0}},
345 {{800, 800, 0.0}, {1.0, 1.0}},
346 {{100, 800, 0.0}, {0.0, 1.0}},
350 ASSERT_TRUE(vertex_buffer);
352 auto bridge = CreateTextureForFixture(
"bay_bridge.jpg");
353 auto boston = CreateTextureForFixture(
"boston.jpg");
354 ASSERT_TRUE(bridge && boston);
356 ASSERT_TRUE(sampler);
358 std::shared_ptr<RenderPass> r2t_pass;
359 auto cmd_buffer =
context->CreateCommandBuffer();
360 ASSERT_TRUE(cmd_buffer);
367 ASSERT_NE(pipeline_desc->GetColorAttachmentDescriptor(0u),
nullptr);
368 texture_descriptor.
format =
369 pipeline_desc->GetColorAttachmentDescriptor(0u)->format;
371 texture_descriptor.
size = {400, 400};
376 context->GetResourceAllocator()->CreateTexture(texture_descriptor);
380 color0.
texture->SetLabel(
"r2t_target");
387 stencil_texture_desc.
size = texture_descriptor.
size;
391 context->GetResourceAllocator()->CreateTexture(stencil_texture_desc);
396 r2t_pass = cmd_buffer->CreateRenderPass(r2t_desc);
397 ASSERT_TRUE(r2t_pass && r2t_pass->IsValid());
400 r2t_pass->SetCommandLabel(
"Box");
401 r2t_pass->SetPipeline(box_pipeline);
402 r2t_pass->SetVertexBuffer(vertex_buffer);
404 FS::FrameInfo frame_info;
405 frame_info.current_time = GetSecondsElapsed();
406 frame_info.cursor_position = GetCursorPosition();
407 frame_info.window_size.x = GetWindowSize().width;
408 frame_info.window_size.y = GetWindowSize().height;
410 FS::BindFrameInfo(*r2t_pass, data_host_buffer->EmplaceUniform(frame_info));
411 FS::BindContents1(*r2t_pass, boston, sampler);
412 FS::BindContents2(*r2t_pass, bridge, sampler);
414 VS::UniformBuffer uniforms;
417 VS::BindUniformBuffer(*r2t_pass, data_host_buffer->EmplaceUniform(uniforms));
418 ASSERT_TRUE(r2t_pass->Draw().ok());
419 ASSERT_TRUE(r2t_pass->EncodeCommands());
420 ASSERT_TRUE(
context->FlushCommandBuffers());
430 GTEST_SKIP() <<
"This test's instance-ID mechanism requires OpenGL ES 3.1; "
431 "CanRenderInstancedWithVertexAttributes covers the "
432 "portable instance-rate path.";
434 using VS = InstancedDrawVertexShader;
435 using FS = InstancedDrawFragmentShader;
439 VS::PerVertexData{
Point{10, 10}},
440 VS::PerVertexData{
Point{10, 110}},
441 VS::PerVertexData{
Point{110, 10}},
442 VS::PerVertexData{
Point{10, 110}},
443 VS::PerVertexData{
Point{110, 10}},
444 VS::PerVertexData{
Point{110, 110}},
447 ASSERT_NE(GetContext(),
nullptr);
450 ->GetPipelineLibrary()
454 .SetStencilAttachmentDescriptors(std::nullopt))
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();
493 GTEST_SKIP() <<
"Mipmap test shader not supported on GLES.";
498 using VS = MipmapsVertexShader;
499 using FS = MipmapsFragmentShader;
501 ASSERT_TRUE(desc.has_value());
503 desc->SetStencilAttachmentDescriptors(std::nullopt);
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");
555 pass->AddCopy(bridge,
texture);
557 if (!pass->EncodeCommands()) {
563 auto pass =
buffer->CreateRenderPass(render_target);
567 pass->SetLabel(
"Playground Render Pass");
569 pass->SetCommandLabel(
"Image");
570 pass->SetPipeline(mipmaps_pipeline);
571 pass->SetVertexBuffer(vertex_buffer);
573 VS::FrameInfo frame_info;
574 EXPECT_EQ(pass->GetOrthographicTransform(),
576 frame_info.mvp = pass->GetOrthographicTransform() *
578 VS::BindFrameInfo(*pass, data_host_buffer->EmplaceUniform(frame_info));
580 FS::FragInfo frag_info;
582 FS::BindFragInfo(*pass, data_host_buffer->EmplaceUniform(frag_info));
584 auto sampler =
context->GetSamplerLibrary()->GetSampler({});
585 FS::BindTex(*pass,
texture, sampler);
589 pass->EncodeCommands();
592 if (!
context->GetCommandQueue()->Submit({buffer}).ok()) {
595 data_host_buffer->Reset();
604 GTEST_SKIP() <<
"Mipmap test shader not supported on GLES.";
609 using VS = MipmapsVertexShader;
610 using FS = MipmapsFragmentShader;
612 ASSERT_TRUE(desc.has_value());
614 desc->SetStencilAttachmentDescriptors(std::nullopt);
615 auto mipmaps_pipeline =
616 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
617 ASSERT_TRUE(mipmaps_pipeline);
619 auto bridge = CreateTextureForFixture(
"bay_bridge.jpg");
620 auto boston = CreateTextureForFixture(
"boston.jpg");
621 ASSERT_TRUE(bridge && boston);
623 ASSERT_TRUE(sampler);
628 texture_desc.
size = bridge->GetTextureDescriptor().size;
634 device_buffer_desc.
size =
635 bridge->GetTextureDescriptor().GetByteSizeOfBaseMipLevel();
637 context->GetResourceAllocator()->CreateBuffer(device_buffer_desc);
644 {{0, 0}, {0.0, 0.0}},
645 {{
size.x, 0}, {1.0, 0.0}},
647 {{0, 0}, {0.0, 0.0}},
649 {{0,
size.y}, {0.0, 1.0}},
653 ASSERT_TRUE(vertex_buffer);
655 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(
context);
662 buffer->SetLabel(
"Playground Command Buffer");
663 auto pass =
buffer->CreateBlitPass();
667 pass->SetLabel(
"Playground Blit Pass");
670 pass->AddCopy(bridge, device_buffer);
671 pass->EncodeCommands();
683 buffer->SetLabel(
"Playground Command Buffer");
685 auto pass =
buffer->CreateRenderPass(render_target);
689 pass->SetLabel(
"Playground Render Pass");
691 pass->SetCommandLabel(
"Image");
692 pass->SetPipeline(mipmaps_pipeline);
693 pass->SetVertexBuffer(vertex_buffer);
695 VS::FrameInfo frame_info;
696 EXPECT_EQ(pass->GetOrthographicTransform(),
698 frame_info.mvp = pass->GetOrthographicTransform() *
700 VS::BindFrameInfo(*pass, data_host_buffer->EmplaceUniform(frame_info));
702 FS::FragInfo frag_info;
704 FS::BindFragInfo(*pass, data_host_buffer->EmplaceUniform(frag_info));
707 context->GetSamplerLibrary()->GetSampler({});
710 context->GetResourceAllocator()->CreateTexture(texture_desc);
711 if (!
texture->SetContents(device_buffer->OnGetContents(),
712 buffer_view.GetRange().length)) {
716 FS::BindTex(*pass,
texture, sampler);
720 pass->EncodeCommands();
721 if (!
context->GetCommandQueue()->Submit({buffer}).ok()) {
725 data_host_buffer->Reset();
734 GTEST_SKIP() <<
"Mipmap test shader not supported on GLES.";
739 using VS = MipmapsVertexShader;
740 using FS = MipmapsFragmentShader;
742 ASSERT_TRUE(desc.has_value());
744 desc->SetStencilAttachmentDescriptors(std::nullopt);
745 auto mipmaps_pipeline =
746 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
747 ASSERT_TRUE(mipmaps_pipeline);
749 auto boston = CreateTextureForFixture(
"boston.jpg",
true);
757 {{0, 0}, {0.0, 0.0}},
758 {{
size.x, 0}, {1.0, 0.0}},
760 {{0, 0}, {0.0, 0.0}},
762 {{0,
size.y}, {0.0, 1.0}},
766 ASSERT_TRUE(vertex_buffer);
768 bool first_frame =
true;
769 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(
context);
771 const char* mip_filter_names[] = {
"Base",
"Nearest",
"Linear"};
774 const char* min_filter_names[] = {
"Nearest",
"Linear"};
779 static int selected_mip_filter = 1;
780 static int selected_min_filter = 0;
781 static float lod = 4.5;
783 ImGui::Begin(
"Controls",
nullptr, ImGuiWindowFlags_AlwaysAutoResize);
784 ImGui::Combo(
"Mip filter", &selected_mip_filter, mip_filter_names,
785 sizeof(mip_filter_names) /
sizeof(
char*));
786 ImGui::Combo(
"Min filter", &selected_min_filter, min_filter_names,
787 sizeof(min_filter_names) /
sizeof(
char*));
788 ImGui::SliderFloat(
"LOD", &lod, 0, boston->GetMipCount() - 1);
795 buffer->SetLabel(
"Playground Command Buffer");
798 auto pass =
buffer->CreateBlitPass();
802 pass->SetLabel(
"Playground Blit Pass");
804 pass->GenerateMipmap(boston,
"Boston Mipmap");
806 pass->EncodeCommands();
812 auto pass =
buffer->CreateRenderPass(render_target);
816 pass->SetLabel(
"Playground Render Pass");
818 pass->SetCommandLabel(
"Image LOD");
819 pass->SetPipeline(mipmaps_pipeline);
820 pass->SetVertexBuffer(vertex_buffer);
822 VS::FrameInfo frame_info;
823 EXPECT_EQ(pass->GetOrthographicTransform(),
825 frame_info.mvp = pass->GetOrthographicTransform() *
827 VS::BindFrameInfo(*pass, data_host_buffer->EmplaceUniform(frame_info));
829 FS::FragInfo frag_info;
831 FS::BindFragInfo(*pass, data_host_buffer->EmplaceUniform(frag_info));
834 sampler_desc.
mip_filter = mip_filters[selected_mip_filter];
835 sampler_desc.
min_filter = min_filters[selected_min_filter];
837 context->GetSamplerLibrary()->GetSampler(sampler_desc);
838 FS::BindTex(*pass, boston, sampler);
842 pass->EncodeCommands();
845 if (!
context->GetCommandQueue()->Submit({buffer}).ok()) {
848 data_host_buffer->Reset();
855 using VS = ImpellerVertexShader;
856 using FS = ImpellerFragmentShader;
859 auto pipeline_descriptor =
861 ASSERT_TRUE(pipeline_descriptor.has_value());
863 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
865 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
868 auto blue_noise = CreateTextureForFixture(
"blue_noise.png");
873 context->GetSamplerLibrary()->GetSampler(noise_sampler_desc);
875 auto cube_map = CreateTextureCubeForFixture(
876 {
"table_mountain_px.png",
"table_mountain_nx.png",
877 "table_mountain_py.png",
"table_mountain_ny.png",
878 "table_mountain_pz.png",
"table_mountain_nz.png"});
880 context->GetSamplerLibrary()->GetSampler({});
882 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(
context);
884 auto size = pass.GetRenderTargetSize();
887 pass.SetCommandLabel(
"Impeller SDF scene");
895 pass.SetVertexBuffer(
898 VS::FrameInfo frame_info;
900 frame_info.mvp = pass.GetOrthographicTransform();
901 VS::BindFrameInfo(pass, data_host_buffer->EmplaceUniform(frame_info));
903 FS::FragInfo fs_uniform;
905 fs_uniform.time = GetSecondsElapsed();
906 FS::BindFragInfo(pass, data_host_buffer->EmplaceUniform(fs_uniform));
907 FS::BindBlueNoise(pass, blue_noise, noise_sampler);
908 FS::BindCubeMap(pass, cube_map, cube_map_sampler);
911 data_host_buffer->Reset();
918 using VS = PlanetVertexShader;
919 using FS = PlanetFragmentShader;
922 auto pipeline_descriptor =
924 ASSERT_TRUE(pipeline_descriptor.has_value());
926 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
928 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
931 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(
context);
933 static Scalar speed = 0.1;
934 static Scalar planet_size = 550.0;
935 static bool show_normals =
false;
936 static bool show_noise =
false;
937 static Scalar seed_value = 42.0;
939 auto size = pass.GetRenderTargetSize();
941 ImGui::Begin(
"Controls",
nullptr, ImGuiWindowFlags_AlwaysAutoResize);
942 ImGui::SliderFloat(
"Speed", &speed, 0.0, 10.0);
943 ImGui::SliderFloat(
"Planet Size", &planet_size, 0.1, 1000);
944 ImGui::Checkbox(
"Show Normals", &show_normals);
945 ImGui::Checkbox(
"Show Noise", &show_noise);
946 ImGui::InputFloat(
"Seed Value", &seed_value);
950 pass.SetCommandLabel(
"Planet scene");
958 pass.SetVertexBuffer(
961 VS::FrameInfo frame_info;
963 frame_info.mvp = pass.GetOrthographicTransform();
964 VS::BindFrameInfo(pass, data_host_buffer->EmplaceUniform(frame_info));
966 FS::FragInfo fs_uniform;
968 fs_uniform.time = GetSecondsElapsed();
969 fs_uniform.speed = speed;
970 fs_uniform.planet_size = planet_size;
971 fs_uniform.show_normals = show_normals ? 1.0 : 0.0;
972 fs_uniform.show_noise = show_noise ? 1.0 : 0.0;
973 fs_uniform.seed_value = seed_value;
974 FS::BindFragInfo(pass, data_host_buffer->EmplaceUniform(fs_uniform));
977 data_host_buffer->Reset();
984 using VS = ArrayVertexShader;
985 using FS = ArrayFragmentShader;
988 auto pipeline_descriptor =
990 ASSERT_TRUE(pipeline_descriptor.has_value());
992 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
994 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
997 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(
context);
999 auto size = pass.GetRenderTargetSize();
1002 pass.SetCommandLabel(
"Google Dots");
1010 pass.SetVertexBuffer(
1013 VS::FrameInfo frame_info;
1017 VS::BindFrameInfo(pass, data_host_buffer->EmplaceUniform(frame_info));
1019 auto time = GetSecondsElapsed();
1020 auto y_pos = [&time](
float x) {
1021 return 400 + 10 * std::cos(time * 5 +
x / 6);
1024 FS::FragInfo fs_uniform = {
1025 .circle_positions = {
Point(430, y_pos(0)),
Point(480, y_pos(1)),
1032 FS::BindFragInfo(pass, data_host_buffer->EmplaceUniform(fs_uniform));
1035 data_host_buffer->Reset();
1042 using VS = InactiveUniformsVertexShader;
1043 using FS = InactiveUniformsFragmentShader;
1046 auto pipeline_descriptor =
1048 ASSERT_TRUE(pipeline_descriptor.has_value());
1050 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
1052 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
1055 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(
context);
1057 auto size = pass.GetRenderTargetSize();
1060 pass.SetCommandLabel(
"Inactive Uniform");
1069 pass.SetVertexBuffer(
1072 VS::FrameInfo frame_info;
1076 VS::BindFrameInfo(pass, data_host_buffer->EmplaceUniform(frame_info));
1078 FS::FragInfo fs_uniform = {.unused_color =
Color::Red(),
1080 FS::BindFragInfo(pass, data_host_buffer->EmplaceUniform(fs_uniform));
1083 data_host_buffer->Reset();
1090 using VS = BoxFadeVertexShader;
1100 using VS = BoxFadeVertexShader;
1109 using VS = BoxFadeVertexShader;
1113 {{100, 100, 0.0}, {0.0, 0.0}},
1114 {{800, 100, 0.0}, {1.0, 0.0}},
1115 {{800, 800, 0.0}, {1.0, 1.0}},
1116 {{100, 800, 0.0}, {0.0, 1.0}},
1132 labels_.push_back(
"Never");
1134 labels_.push_back(
"Always");
1136 labels_.push_back(
"Less");
1138 labels_.push_back(
"Equal");
1140 labels_.push_back(
"LessEqual");
1142 labels_.push_back(
"Greater");
1144 labels_.push_back(
"NotEqual");
1146 labels_.push_back(
"GreaterEqual");
1148 assert(labels_.size() == functions_.size());
1151 const char*
const*
labels()
const {
return &labels_[0]; }
1153 int size()
const {
return labels_.size(); }
1156 for (
size_t i = 0;
i < functions_.size();
i++) {
1157 if (functions_[
i] == func) {
1168 std::vector<const char*> labels_;
1169 std::vector<CompareFunction> functions_;
1178 using VS = BoxFadeVertexShader;
1179 using FS = BoxFadeFragmentShader;
1183 auto desc = BoxFadePipelineBuilder::MakeDefaultPipelineDescriptor(*
context);
1184 ASSERT_TRUE(desc.has_value());
1190 {{100, 100, 0.0}, {0.0, 0.0}},
1191 {{800, 100, 0.0}, {1.0, 0.0}},
1192 {{800, 800, 0.0}, {1.0, 1.0}},
1193 {{100, 100, 0.0}, {0.0, 0.0}},
1194 {{800, 800, 0.0}, {1.0, 1.0}},
1195 {{100, 800, 0.0}, {0.0, 1.0}},
1197 auto vertex_buffer =
1199 ASSERT_TRUE(vertex_buffer);
1202 desc->SetStencilAttachmentDescriptors(std::nullopt);
1204 auto bridge = CreateTextureForFixture(
"bay_bridge.jpg");
1205 auto boston = CreateTextureForFixture(
"boston.jpg");
1206 ASSERT_TRUE(bridge && boston);
1208 ASSERT_TRUE(sampler);
1210 static bool mirror =
false;
1211 static int stencil_reference_write = 0xFF;
1212 static int stencil_reference_read = 0x1;
1213 std::vector<uint8_t> stencil_contents;
1214 static int last_stencil_contents_reference_value = 0;
1215 static int current_front_compare =
1217 static int current_back_compare =
1220 auto [data_host_buffer, indexes_host_buffer] = createHostBuffers(
context);
1226 buffer->SetLabel(
"Playground Command Buffer");
1234 render_target.SetupDepthStencilAttachments(
1236 render_target.GetRenderTargetSize(),
true,
"stencil", stencil_config);
1238 const auto target_width = render_target.GetRenderTargetSize().width;
1239 const auto target_height = render_target.GetRenderTargetSize().height;
1240 const size_t target_size = target_width * target_height;
1241 if (stencil_contents.size() != target_size ||
1242 last_stencil_contents_reference_value != stencil_reference_write) {
1243 stencil_contents.resize(target_size);
1244 last_stencil_contents_reference_value = stencil_reference_write;
1245 for (
int y = 0;
y < target_height;
y++) {
1246 for (
int x = 0;
x < target_width;
x++) {
1247 const auto index =
y * target_width +
x;
1248 const auto kCheckSize = 64;
1250 (((
y / kCheckSize) + (
x / kCheckSize)) % 2 == 0) *
1251 stencil_reference_write;
1252 stencil_contents[index] =
value;
1256 if (!render_target.GetStencilAttachment()->texture->SetContents(
1257 stencil_contents.data(), stencil_contents.size(), 0,
false)) {
1258 VALIDATION_LOG <<
"Could not upload stencil contents to device memory";
1261 auto pass =
buffer->CreateRenderPass(render_target);
1265 pass->SetLabel(
"Stencil Buffer");
1266 ImGui::Begin(
"Controls",
nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1267 ImGui::SliderInt(
"Stencil Write Value", &stencil_reference_write, 0,
1269 ImGui::SliderInt(
"Stencil Compare Value", &stencil_reference_read, 0,
1271 ImGui::Checkbox(
"Back face mode", &mirror);
1272 ImGui::ListBox(
"Front face compare function", ¤t_front_compare,
1274 ImGui::ListBox(
"Back face compare function", ¤t_back_compare,
1284 desc->SetStencilAttachmentDescriptors(front, back);
1285 auto pipeline =
context->GetPipelineLibrary()->GetPipeline(desc).Get();
1289 pass->SetCommandLabel(
"Box");
1291 pass->SetStencilReference(stencil_reference_read);
1292 pass->SetVertexBuffer(vertex_buffer);
1294 VS::UniformBuffer uniforms;
1295 EXPECT_EQ(pass->GetOrthographicTransform(),
1297 uniforms.mvp = pass->GetOrthographicTransform() *
1302 VS::BindUniformBuffer(*pass, data_host_buffer->EmplaceUniform(uniforms));
1304 FS::FrameInfo frame_info;
1305 frame_info.current_time = GetSecondsElapsed();
1306 frame_info.cursor_position = GetCursorPosition();
1307 frame_info.window_size.x = GetWindowSize().width;
1308 frame_info.window_size.y = GetWindowSize().height;
1310 FS::BindFrameInfo(*pass, data_host_buffer->EmplaceUniform(frame_info));
1311 FS::BindContents1(*pass, boston, sampler);
1312 FS::BindContents2(*pass, bridge, sampler);
1313 if (!pass->Draw().ok()) {
1316 pass->EncodeCommands();
1319 if (!
context->GetCommandQueue()->Submit({buffer}).ok()) {
1322 data_host_buffer->Reset();
1330 auto cmd_buffer =
context->CreateCommandBuffer();
1331 auto render_target_cache = std::make_shared<RenderTargetAllocator>(
1332 GetContext()->GetResourceAllocator());
1334 auto render_target = render_target_cache->CreateOffscreen(
1336 auto render_pass = cmd_buffer->CreateRenderPass(render_target);
1338 EXPECT_EQ(
render_pass->GetSampleCount(), render_target.GetSampleCount());
1339 EXPECT_EQ(
render_pass->GetRenderTargetPixelFormat(),
1340 render_target.GetRenderTargetPixelFormat());
1342 render_target.GetStencilAttachment().has_value());
1344 render_target.GetRenderTargetSize());
1349 RenderTargetCreateOffscreenMSAASetsDefaultDepthStencilFormat) {
1351 auto render_target_cache = std::make_shared<RenderTargetAllocator>(
1352 GetContext()->GetResourceAllocator());
1354 RenderTarget render_target = render_target_cache->CreateOffscreenMSAA(
1357 ->texture->GetTextureDescriptor()
1359 GetContext()->GetCapabilities()->GetDefaultDepthStencilFormat());
1362template <
class VertexShader,
class FragmentShader>
1364 const std::shared_ptr<Context>&
context) {
1366 auto pipeline_desc =
1367 TexturePipelineBuilder::MakeDefaultPipelineDescriptor(*
context);
1368 if (!pipeline_desc.has_value()) {
1372 pipeline_desc->SetStencilAttachmentDescriptors(std::nullopt);
1374 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
1383 using TextureVS = TextureVertexShader;
1384 using TextureFS = TextureFragmentShader;
1386 using SepiaVS = SepiaVertexShader;
1387 using SepiaFS = SepiaFragmentShader;
1392 if (!
context->GetCapabilities()->SupportsFramebufferFetch()) {
1393 GTEST_SKIP() <<
"This test uses framebuffer fetch and the backend doesn't "
1399 auto texture_pipeline = CreateDefaultPipeline<TextureVS, TextureFS>(
context);
1400 auto sepia_pipeline = CreateDefaultPipeline<SepiaVS, SepiaFS>(
context);
1402 ASSERT_TRUE(texture_pipeline);
1403 ASSERT_TRUE(sepia_pipeline);
1408 {{100, 100, 0.0}, {0.0, 0.0}},
1409 {{800, 100, 0.0}, {1.0, 0.0}},
1410 {{800, 800, 0.0}, {1.0, 1.0}},
1411 {{100, 100, 0.0}, {0.0, 0.0}},
1412 {{800, 800, 0.0}, {1.0, 1.0}},
1413 {{100, 800, 0.0}, {0.0, 1.0}},
1426 auto boston = CreateTextureForFixture(
"boston.jpg");
1427 ASSERT_TRUE(boston);
1429 const auto& sampler =
context->GetSamplerLibrary()->GetSampler({});
1430 ASSERT_TRUE(sampler);
1434 context->GetCapabilities()->GetMinimumUniformAlignment());
1438 pass.SetPipeline(texture_pipeline);
1440 *
context->GetResourceAllocator()));
1441 TextureVS::UniformBuffer uniforms;
1444 TextureVS::BindUniformBuffer(pass,
buffer->EmplaceUniform(uniforms));
1445 TextureFS::BindTextureContents(pass, boston, sampler);
1446 if (!pass.Draw().ok()) {
1453 pass.SetPipeline(sepia_pipeline);
1455 *
context->GetResourceAllocator()));
1456 SepiaVS::UniformBuffer uniforms;
1459 SepiaVS::BindUniformBuffer(pass,
buffer->EmplaceUniform(uniforms));
1460 if (!pass.Draw().ok()) {
1472 using TextureVS = TextureVertexShader;
1473 using TextureFS = TextureFragmentShader;
1475 using SwizzleVS = SepiaVertexShader;
1476 using SwizzleFS = SwizzleFragmentShader;
1478 using SepiaVS = SepiaVertexShader;
1479 using SepiaFS = SepiaFragmentShader;
1484 if (!
context->GetCapabilities()->SupportsFramebufferFetch()) {
1485 GTEST_SKIP() <<
"This test uses framebuffer fetch and the backend doesn't "
1491 auto texture_pipeline = CreateDefaultPipeline<TextureVS, TextureFS>(
context);
1492 auto swizzle_pipeline = CreateDefaultPipeline<SwizzleVS, SwizzleFS>(
context);
1493 auto sepia_pipeline = CreateDefaultPipeline<SepiaVS, SepiaFS>(
context);
1495 ASSERT_TRUE(texture_pipeline);
1496 ASSERT_TRUE(swizzle_pipeline);
1497 ASSERT_TRUE(sepia_pipeline);
1502 {{100, 100, 0.0}, {0.0, 0.0}},
1503 {{800, 100, 0.0}, {1.0, 0.0}},
1504 {{800, 800, 0.0}, {1.0, 1.0}},
1505 {{100, 100, 0.0}, {0.0, 0.0}},
1506 {{800, 800, 0.0}, {1.0, 1.0}},
1507 {{100, 800, 0.0}, {0.0, 1.0}},
1520 auto boston = CreateTextureForFixture(
"boston.jpg");
1521 ASSERT_TRUE(boston);
1523 const auto& sampler =
context->GetSamplerLibrary()->GetSampler({});
1524 ASSERT_TRUE(sampler);
1528 context->GetCapabilities()->GetMinimumUniformAlignment());
1532 pass.SetPipeline(texture_pipeline);
1534 *
context->GetResourceAllocator()));
1535 TextureVS::UniformBuffer uniforms;
1538 TextureVS::BindUniformBuffer(pass, data_buffer->EmplaceUniform(uniforms));
1539 TextureFS::BindTextureContents(pass, boston, sampler);
1540 if (!pass.Draw().ok()) {
1547 pass.SetPipeline(sepia_pipeline);
1549 *
context->GetResourceAllocator()));
1550 SepiaVS::UniformBuffer uniforms;
1553 SepiaVS::BindUniformBuffer(pass, data_buffer->EmplaceUniform(uniforms));
1554 if (!pass.Draw().ok()) {
1561 pass.SetPipeline(swizzle_pipeline);
1563 *
context->GetResourceAllocator()));
1564 SwizzleVS::UniformBuffer uniforms;
1567 SwizzleVS::BindUniformBuffer(pass, data_buffer->EmplaceUniform(uniforms));
1568 if (!pass.Draw().ok()) {
1579 using FS = BoxFadeFragmentShader;
1589 EXPECT_FALSE(FS::BindContents2(*pass,
nullptr, sampler));
1603 desc.
size = {100, 100};
1605 auto texture =
context->GetResourceAllocator()->CreateTexture(desc);
1619 ASSERT_TRUE(pass && pass->IsValid());
1620 pass->EncodeCommands();
1621 EXPECT_TRUE(
context->GetCommandQueue()->Submit({buffer}).ok());
1630 GTEST_SKIP() <<
"Rendering to non-zero mip levels is gated on a GLES "
1631 "capability; covered by the Metal and Vulkan backends.";
1639 desc.
size = {100, 100};
1642 auto texture =
context->GetResourceAllocator()->CreateTexture(desc);
1654 EXPECT_EQ(
target.GetRenderTargetSize(),
ISize(50, 50));
1658 ASSERT_TRUE(pass && pass->IsValid());
1659 pass->EncodeCommands();
1660 EXPECT_TRUE(
context->GetCommandQueue()->Submit({buffer}).ok());
1671 desc.
size = {100, 100};
1674 auto texture =
context->GetResourceAllocator()->CreateTexture(desc);
1681 EXPECT_TRUE(color0.
IsValid());
1687 EXPECT_FALSE(color0.
IsValid());
1691 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::function< bool(RenderTarget &render_target)> RenderCallback
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.
LinePipeline::FragmentShader FS
@ 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.
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 (...
@ 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
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...