5 #include "flutter/fml/logging.h"
6 #include "flutter/fml/time/time_point.h"
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"
54 using VS = BoxFadeVertexShader;
55 using FS = BoxFadeFragmentShader;
56 auto context = GetContext();
59 auto desc = BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
60 ASSERT_TRUE(desc.has_value());
62 desc->SetStencilAttachmentDescriptors(std::nullopt);
68 {{100, 100, 0.0}, {0.0, 0.0}},
69 {{800, 100, 0.0}, {1.0, 0.0}},
70 {{800, 800, 0.0}, {1.0, 1.0}},
71 {{100, 100, 0.0}, {0.0, 0.0}},
72 {{800, 800, 0.0}, {1.0, 1.0}},
73 {{100, 800, 0.0}, {0.0, 1.0}},
75 auto bridge = CreateTextureForFixture(
"bay_bridge.jpg");
76 auto boston = CreateTextureForFixture(
"boston.jpg");
77 ASSERT_TRUE(bridge && boston);
82 context->GetIdleWaiter());
83 SinglePassCallback callback = [&](
RenderPass& pass) {
84 ImGui::Begin(
"Controls",
nullptr, ImGuiWindowFlags_AlwaysAutoResize);
85 static bool wireframe;
86 ImGui::Checkbox(
"Wireframe", &wireframe);
90 auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get();
92 assert(pipeline && pipeline->IsValid());
94 pass.SetCommandLabel(
"Box");
95 pass.SetPipeline(pipeline);
99 VS::UniformBuffer uniforms;
100 EXPECT_EQ(pass.GetOrthographicTransform(),
104 VS::BindUniformBuffer(pass, host_buffer->EmplaceUniform(uniforms));
106 FS::FrameInfo frame_info;
107 frame_info.current_time = GetSecondsElapsed();
108 frame_info.cursor_position = GetCursorPosition();
109 frame_info.window_size.x = GetWindowSize().width;
110 frame_info.window_size.y = GetWindowSize().height;
112 FS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
113 FS::BindContents1(pass, boston, sampler);
114 FS::BindContents2(pass, bridge, sampler);
116 host_buffer->Reset();
117 return pass.Draw().ok();
119 OpenPlaygroundHere(callback);
123 auto context = GetContext();
124 ASSERT_TRUE(context);
127 using VS = BabyVertexShader;
128 using FS = BabyFragmentShader;
136 ASSERT_TRUE(desc.has_value());
140 desc->SetStencilAttachmentDescriptors(std::nullopt);
144 auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get();
148 context->GetIdleWaiter());
159 *context->GetResourceAllocator());
161 SinglePassCallback callback = [&](
RenderPass& pass) {
162 pass.SetPipeline(pipeline);
163 pass.SetVertexBuffer(vertex_buffer);
165 FS::FragInfo frag_info;
166 frag_info.time = fml::TimePoint::Now().ToEpochDelta().ToSecondsF();
169 context->GetIdleWaiter());
170 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(frag_info));
172 return pass.Draw().ok();
174 OpenPlaygroundHere(callback);
178 using VS = ColorsVertexShader;
179 using FS = ColorsFragmentShader;
180 auto context = GetContext();
181 ASSERT_TRUE(context);
183 ASSERT_TRUE(desc.has_value());
187 desc->ClearStencilAttachments();
191 auto vertex_desc = std::make_shared<VertexDescriptor>();
198 const std::vector<ShaderStageIOSlot> io_slots = {position_slot, color_slot};
199 const std::vector<ShaderStageBufferLayout> layouts = {
202 vertex_desc->RegisterDescriptorSetLayouts(VS::kDescriptorSetLayouts);
203 vertex_desc->RegisterDescriptorSetLayouts(FS::kDescriptorSetLayouts);
204 vertex_desc->SetStageInputs(io_slots, layouts);
205 desc->SetVertexDescriptor(std::move(vertex_desc));
207 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
208 ASSERT_TRUE(pipeline);
227 uint16_t indices[36] = {
237 auto device_buffer = context->GetResourceAllocator()->CreateBufferWithCopy(
238 reinterpret_cast<uint8_t*
>(&cube),
sizeof(cube));
241 ASSERT_TRUE(sampler);
245 context->GetIdleWaiter());
246 SinglePassCallback callback = [&](
RenderPass& pass) {
250 ImGui::Begin(
"Controls",
nullptr, ImGuiWindowFlags_AlwaysAutoResize);
251 ImGui::SliderFloat(
"Field of view", &fov_y.
degrees, 0, 180);
252 ImGui::SliderFloat(
"Camera distance", &
distance, 0, 30);
255 pass.SetCommandLabel(
"Perspective Cube");
256 pass.SetPipeline(pipeline);
258 std::array<BufferView, 2> vertex_buffers = {
260 Range(offsetof(Cube, positions),
sizeof(Cube::positions))),
262 Range(offsetof(Cube, colors),
sizeof(Cube::colors))),
266 device_buffer,
Range(offsetof(Cube, indices),
sizeof(Cube::indices)));
267 pass.SetVertexBuffer(vertex_buffers.data(), vertex_buffers.size());
268 pass.SetElementCount(36);
271 VS::UniformBuffer uniforms;
272 Scalar time = GetSecondsElapsed();
273 euler_angles =
Vector3(0.19 * time, 0.7 * time, 0.43 * time);
281 VS::BindUniformBuffer(pass, host_buffer->EmplaceUniform(uniforms));
283 host_buffer->Reset();
284 return pass.Draw().ok();
286 OpenPlaygroundHere(callback);
290 using VS = BoxFadeVertexShader;
291 using FS = BoxFadeFragmentShader;
292 auto context = GetContext();
293 ASSERT_TRUE(context);
295 auto desc = BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
296 ASSERT_TRUE(desc.has_value());
298 desc->SetStencilAttachmentDescriptors(std::nullopt);
300 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
301 ASSERT_TRUE(box_pipeline);
307 {{100, 100, 0.0}, {0.0, 0.0}},
308 {{800, 100, 0.0}, {1.0, 0.0}},
309 {{800, 800, 0.0}, {1.0, 1.0}},
310 {{100, 100, 0.0}, {0.0, 0.0}},
311 {{800, 800, 0.0}, {1.0, 1.0}},
312 {{100, 800, 0.0}, {0.0, 1.0}},
316 ASSERT_TRUE(vertex_buffer);
318 auto bridge = CreateTextureForFixture(
"bay_bridge.jpg");
319 auto boston = CreateTextureForFixture(
"boston.jpg");
320 ASSERT_TRUE(bridge && boston);
322 ASSERT_TRUE(sampler);
325 context->GetIdleWaiter());
326 SinglePassCallback callback = [&](
RenderPass& pass) {
327 for (
size_t i = 0; i < 1; i++) {
328 for (
size_t j = 0; j < 1; j++) {
329 pass.SetCommandLabel(
"Box");
330 pass.SetPipeline(box_pipeline);
331 pass.SetVertexBuffer(vertex_buffer);
333 FS::FrameInfo frame_info;
334 frame_info.current_time = GetSecondsElapsed();
335 frame_info.cursor_position = GetCursorPosition();
336 frame_info.window_size.x = GetWindowSize().width;
337 frame_info.window_size.y = GetWindowSize().height;
339 FS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
340 FS::BindContents1(pass, boston, sampler);
341 FS::BindContents2(pass, bridge, sampler);
343 VS::UniformBuffer uniforms;
344 EXPECT_EQ(pass.GetOrthographicTransform(),
346 uniforms.mvp = pass.GetOrthographicTransform() *
349 VS::BindUniformBuffer(pass, host_buffer->EmplaceUniform(uniforms));
350 if (!pass.Draw().ok()) {
356 host_buffer->Reset();
359 OpenPlaygroundHere(callback);
363 using VS = BoxFadeVertexShader;
364 using FS = BoxFadeFragmentShader;
365 auto context = GetContext();
366 ASSERT_TRUE(context);
369 BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
371 pipeline_desc->ClearDepthAttachment();
374 ASSERT_TRUE(pipeline_desc.has_value());
376 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
377 ASSERT_TRUE(box_pipeline);
379 context->GetIdleWaiter());
384 {{100, 100, 0.0}, {0.0, 0.0}},
385 {{800, 100, 0.0}, {1.0, 0.0}},
386 {{800, 800, 0.0}, {1.0, 1.0}},
387 {{100, 100, 0.0}, {0.0, 0.0}},
388 {{800, 800, 0.0}, {1.0, 1.0}},
389 {{100, 800, 0.0}, {0.0, 1.0}},
393 ASSERT_TRUE(vertex_buffer);
395 auto bridge = CreateTextureForFixture(
"bay_bridge.jpg");
396 auto boston = CreateTextureForFixture(
"boston.jpg");
397 ASSERT_TRUE(bridge && boston);
399 ASSERT_TRUE(sampler);
401 std::shared_ptr<RenderPass> r2t_pass;
402 auto cmd_buffer = context->CreateCommandBuffer();
403 ASSERT_TRUE(cmd_buffer);
410 ASSERT_NE(pipeline_desc->GetColorAttachmentDescriptor(0u),
nullptr);
411 texture_descriptor.
format =
412 pipeline_desc->GetColorAttachmentDescriptor(0u)->format;
414 texture_descriptor.
size = {400, 400};
419 context->GetResourceAllocator()->CreateTexture(texture_descriptor);
423 color0.
texture->SetLabel(
"r2t_target");
430 stencil_texture_desc.
size = texture_descriptor.
size;
434 context->GetResourceAllocator()->CreateTexture(stencil_texture_desc);
439 r2t_pass = cmd_buffer->CreateRenderPass(r2t_desc);
440 ASSERT_TRUE(r2t_pass && r2t_pass->IsValid());
443 r2t_pass->SetCommandLabel(
"Box");
444 r2t_pass->SetPipeline(box_pipeline);
445 r2t_pass->SetVertexBuffer(vertex_buffer);
447 FS::FrameInfo frame_info;
448 frame_info.current_time = GetSecondsElapsed();
449 frame_info.cursor_position = GetCursorPosition();
450 frame_info.window_size.x = GetWindowSize().width;
451 frame_info.window_size.y = GetWindowSize().height;
453 FS::BindFrameInfo(*r2t_pass, host_buffer->EmplaceUniform(frame_info));
454 FS::BindContents1(*r2t_pass, boston, sampler);
455 FS::BindContents2(*r2t_pass, bridge, sampler);
457 VS::UniformBuffer uniforms;
460 VS::BindUniformBuffer(*r2t_pass, host_buffer->EmplaceUniform(uniforms));
461 ASSERT_TRUE(r2t_pass->Draw().ok());
462 ASSERT_TRUE(r2t_pass->EncodeCommands());
467 GTEST_SKIP() <<
"Instancing is not supported on OpenGL.";
469 using VS = InstancedDrawVertexShader;
470 using FS = InstancedDrawFragmentShader;
474 VS::PerVertexData{
Point{10, 10}},
475 VS::PerVertexData{
Point{10, 110}},
476 VS::PerVertexData{
Point{110, 10}},
477 VS::PerVertexData{
Point{10, 110}},
478 VS::PerVertexData{
Point{110, 10}},
479 VS::PerVertexData{
Point{110, 110}},
482 ASSERT_NE(GetContext(),
nullptr);
485 ->GetPipelineLibrary()
489 .SetStencilAttachmentDescriptors(std::nullopt))
492 ASSERT_TRUE(pipeline && pipeline->IsValid());
494 static constexpr
size_t kInstancesCount = 5u;
495 VS::InstanceInfo<kInstancesCount> instances;
496 for (
size_t i = 0; i < kInstancesCount; i++) {
501 GetContext()->GetIdleWaiter());
502 ASSERT_TRUE(OpenPlaygroundHere([&](
RenderPass& pass) ->
bool {
506 VS::FrameInfo frame_info;
511 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
512 VS::BindInstanceInfo(pass, host_buffer->EmplaceStorageBuffer(instances));
518 host_buffer->Reset();
525 GTEST_SKIP() <<
"Mipmap test shader not supported on GLES.";
527 auto context = GetContext();
528 ASSERT_TRUE(context);
530 using VS = MipmapsVertexShader;
531 using FS = MipmapsFragmentShader;
533 ASSERT_TRUE(desc.has_value());
535 desc->SetStencilAttachmentDescriptors(std::nullopt);
536 auto mipmaps_pipeline =
537 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
538 ASSERT_TRUE(mipmaps_pipeline);
543 texture_desc.
size = {800, 600};
546 auto texture = context->GetResourceAllocator()->CreateTexture(texture_desc);
547 ASSERT_TRUE(texture);
549 auto bridge = CreateTextureForFixture(
"bay_bridge.jpg");
550 auto boston = CreateTextureForFixture(
"boston.jpg");
551 ASSERT_TRUE(bridge && boston);
553 ASSERT_TRUE(sampler);
558 auto size =
Point(boston->GetSize());
560 {{0, 0}, {0.0, 0.0}},
561 {{size.x, 0}, {1.0, 0.0}},
562 {{size.x, size.y}, {1.0, 1.0}},
563 {{0, 0}, {0.0, 0.0}},
564 {{size.x, size.y}, {1.0, 1.0}},
565 {{0, size.y}, {0.0, 1.0}},
569 ASSERT_TRUE(vertex_buffer);
572 context->GetIdleWaiter());
574 auto buffer = context->CreateCommandBuffer();
578 buffer->SetLabel(
"Playground Command Buffer");
581 auto pass = buffer->CreateBlitPass();
585 pass->SetLabel(
"Playground Blit Pass");
588 pass->AddCopy(bridge, texture);
590 if (!pass->EncodeCommands()) {
596 auto pass = buffer->CreateRenderPass(render_target);
600 pass->SetLabel(
"Playground Render Pass");
602 pass->SetCommandLabel(
"Image");
603 pass->SetPipeline(mipmaps_pipeline);
604 pass->SetVertexBuffer(vertex_buffer);
606 VS::FrameInfo frame_info;
607 EXPECT_EQ(pass->GetOrthographicTransform(),
609 frame_info.mvp = pass->GetOrthographicTransform() *
611 VS::BindFrameInfo(*pass, host_buffer->EmplaceUniform(frame_info));
613 FS::FragInfo frag_info;
615 FS::BindFragInfo(*pass, host_buffer->EmplaceUniform(frag_info));
617 auto sampler = context->GetSamplerLibrary()->GetSampler({});
618 FS::BindTex(*pass, texture, sampler);
622 pass->EncodeCommands();
625 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
628 host_buffer->Reset();
631 OpenPlaygroundHere(callback);
636 GTEST_SKIP() <<
"Mipmap test shader not supported on GLES.";
638 auto context = GetContext();
639 ASSERT_TRUE(context);
641 using VS = MipmapsVertexShader;
642 using FS = MipmapsFragmentShader;
644 ASSERT_TRUE(desc.has_value());
646 desc->SetStencilAttachmentDescriptors(std::nullopt);
647 auto mipmaps_pipeline =
648 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
649 ASSERT_TRUE(mipmaps_pipeline);
651 auto bridge = CreateTextureForFixture(
"bay_bridge.jpg");
652 auto boston = CreateTextureForFixture(
"boston.jpg");
653 ASSERT_TRUE(bridge && boston);
655 ASSERT_TRUE(sampler);
660 texture_desc.
size = bridge->GetTextureDescriptor().size;
666 device_buffer_desc.
size =
667 bridge->GetTextureDescriptor().GetByteSizeOfBaseMipLevel();
669 context->GetResourceAllocator()->CreateBuffer(device_buffer_desc);
674 auto size =
Point(boston->GetSize());
676 {{0, 0}, {0.0, 0.0}},
677 {{size.x, 0}, {1.0, 0.0}},
678 {{size.x, size.y}, {1.0, 1.0}},
679 {{0, 0}, {0.0, 0.0}},
680 {{size.x, size.y}, {1.0, 1.0}},
681 {{0, size.y}, {0.0, 1.0}},
685 ASSERT_TRUE(vertex_buffer);
688 context->GetIdleWaiter());
691 auto buffer = context->CreateCommandBuffer();
695 buffer->SetLabel(
"Playground Command Buffer");
696 auto pass = buffer->CreateBlitPass();
700 pass->SetLabel(
"Playground Blit Pass");
703 pass->AddCopy(bridge, device_buffer);
704 pass->EncodeCommands();
706 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
712 auto buffer = context->CreateCommandBuffer();
716 buffer->SetLabel(
"Playground Command Buffer");
718 auto pass = buffer->CreateRenderPass(render_target);
722 pass->SetLabel(
"Playground Render Pass");
724 pass->SetCommandLabel(
"Image");
725 pass->SetPipeline(mipmaps_pipeline);
726 pass->SetVertexBuffer(vertex_buffer);
728 VS::FrameInfo frame_info;
729 EXPECT_EQ(pass->GetOrthographicTransform(),
731 frame_info.mvp = pass->GetOrthographicTransform() *
733 VS::BindFrameInfo(*pass, host_buffer->EmplaceUniform(frame_info));
735 FS::FragInfo frag_info;
737 FS::BindFragInfo(*pass, host_buffer->EmplaceUniform(frag_info));
740 context->GetSamplerLibrary()->GetSampler({});
743 context->GetResourceAllocator()->CreateTexture(texture_desc);
744 if (!texture->SetContents(device_buffer->OnGetContents(),
749 FS::BindTex(*pass, texture, sampler);
753 pass->EncodeCommands();
754 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
758 host_buffer->Reset();
761 OpenPlaygroundHere(callback);
766 GTEST_SKIP() <<
"Mipmap test shader not supported on GLES.";
768 auto context = GetContext();
769 ASSERT_TRUE(context);
771 using VS = MipmapsVertexShader;
772 using FS = MipmapsFragmentShader;
774 ASSERT_TRUE(desc.has_value());
776 desc->SetStencilAttachmentDescriptors(std::nullopt);
777 auto mipmaps_pipeline =
778 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
779 ASSERT_TRUE(mipmaps_pipeline);
781 auto boston = CreateTextureForFixture(
"boston.jpg",
true);
787 auto size =
Point(boston->GetSize());
789 {{0, 0}, {0.0, 0.0}},
790 {{size.x, 0}, {1.0, 0.0}},
791 {{size.x, size.y}, {1.0, 1.0}},
792 {{0, 0}, {0.0, 0.0}},
793 {{size.x, size.y}, {1.0, 1.0}},
794 {{0, size.y}, {0.0, 1.0}},
798 ASSERT_TRUE(vertex_buffer);
800 bool first_frame =
true;
802 context->GetIdleWaiter());
804 const char* mip_filter_names[] = {
"Base",
"Nearest",
"Linear"};
807 const char* min_filter_names[] = {
"Nearest",
"Linear"};
812 static int selected_mip_filter = 1;
813 static int selected_min_filter = 0;
814 static float lod = 4.5;
816 ImGui::Begin(
"Controls",
nullptr, ImGuiWindowFlags_AlwaysAutoResize);
817 ImGui::Combo(
"Mip filter", &selected_mip_filter, mip_filter_names,
818 sizeof(mip_filter_names) /
sizeof(
char*));
819 ImGui::Combo(
"Min filter", &selected_min_filter, min_filter_names,
820 sizeof(min_filter_names) /
sizeof(
char*));
821 ImGui::SliderFloat(
"LOD", &lod, 0, boston->GetMipCount() - 1);
824 auto buffer = context->CreateCommandBuffer();
828 buffer->SetLabel(
"Playground Command Buffer");
831 auto pass = buffer->CreateBlitPass();
835 pass->SetLabel(
"Playground Blit Pass");
837 pass->GenerateMipmap(boston,
"Boston Mipmap");
839 pass->EncodeCommands();
845 auto pass = buffer->CreateRenderPass(render_target);
849 pass->SetLabel(
"Playground Render Pass");
851 pass->SetCommandLabel(
"Image LOD");
852 pass->SetPipeline(mipmaps_pipeline);
853 pass->SetVertexBuffer(vertex_buffer);
855 VS::FrameInfo frame_info;
856 EXPECT_EQ(pass->GetOrthographicTransform(),
858 frame_info.mvp = pass->GetOrthographicTransform() *
860 VS::BindFrameInfo(*pass, host_buffer->EmplaceUniform(frame_info));
862 FS::FragInfo frag_info;
864 FS::BindFragInfo(*pass, host_buffer->EmplaceUniform(frag_info));
867 sampler_desc.
mip_filter = mip_filters[selected_mip_filter];
868 sampler_desc.
min_filter = min_filters[selected_min_filter];
870 context->GetSamplerLibrary()->GetSampler(sampler_desc);
871 FS::BindTex(*pass, boston, sampler);
875 pass->EncodeCommands();
878 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
881 host_buffer->Reset();
884 OpenPlaygroundHere(callback);
888 using VS = ImpellerVertexShader;
889 using FS = ImpellerFragmentShader;
891 auto context = GetContext();
892 auto pipeline_descriptor =
894 ASSERT_TRUE(pipeline_descriptor.has_value());
896 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
898 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
899 ASSERT_TRUE(pipeline && pipeline->IsValid());
901 auto blue_noise = CreateTextureForFixture(
"blue_noise.png");
906 context->GetSamplerLibrary()->GetSampler(noise_sampler_desc);
908 auto cube_map = CreateTextureCubeForFixture(
909 {
"table_mountain_px.png",
"table_mountain_nx.png",
910 "table_mountain_py.png",
"table_mountain_ny.png",
911 "table_mountain_pz.png",
"table_mountain_nz.png"});
913 context->GetSamplerLibrary()->GetSampler({});
915 context->GetIdleWaiter());
917 SinglePassCallback callback = [&](
RenderPass& pass) {
918 auto size = pass.GetRenderTargetSize();
920 pass.SetPipeline(pipeline);
921 pass.SetCommandLabel(
"Impeller SDF scene");
924 {
Point(0, size.height)},
925 {
Point(size.width, 0)},
926 {
Point(size.width, 0)},
927 {
Point(0, size.height)},
928 {
Point(size.width, size.height)}});
931 VS::FrameInfo frame_info;
933 frame_info.mvp = pass.GetOrthographicTransform();
934 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
936 FS::FragInfo fs_uniform;
937 fs_uniform.texture_size =
Point(size);
938 fs_uniform.time = GetSecondsElapsed();
939 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(fs_uniform));
940 FS::BindBlueNoise(pass, blue_noise, noise_sampler);
941 FS::BindCubeMap(pass, cube_map, cube_map_sampler);
944 host_buffer->Reset();
947 OpenPlaygroundHere(callback);
951 using VS = PlanetVertexShader;
952 using FS = PlanetFragmentShader;
954 auto context = GetContext();
955 auto pipeline_descriptor =
957 ASSERT_TRUE(pipeline_descriptor.has_value());
959 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
961 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
962 ASSERT_TRUE(pipeline && pipeline->IsValid());
965 context->GetIdleWaiter());
967 SinglePassCallback callback = [&](
RenderPass& pass) {
968 static Scalar speed = 0.1;
969 static Scalar planet_size = 550.0;
970 static bool show_normals =
false;
971 static bool show_noise =
false;
972 static Scalar seed_value = 42.0;
974 auto size = pass.GetRenderTargetSize();
976 ImGui::Begin(
"Controls",
nullptr, ImGuiWindowFlags_AlwaysAutoResize);
977 ImGui::SliderFloat(
"Speed", &speed, 0.0, 10.0);
978 ImGui::SliderFloat(
"Planet Size", &planet_size, 0.1, 1000);
979 ImGui::Checkbox(
"Show Normals", &show_normals);
980 ImGui::Checkbox(
"Show Noise", &show_noise);
981 ImGui::InputFloat(
"Seed Value", &seed_value);
984 pass.SetPipeline(pipeline);
985 pass.SetCommandLabel(
"Planet scene");
988 {
Point(0, size.height)},
989 {
Point(size.width, 0)},
990 {
Point(size.width, 0)},
991 {
Point(0, size.height)},
992 {
Point(size.width, size.height)}});
995 VS::FrameInfo frame_info;
997 frame_info.mvp = pass.GetOrthographicTransform();
998 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
1000 FS::FragInfo fs_uniform;
1001 fs_uniform.resolution =
Point(size);
1002 fs_uniform.time = GetSecondsElapsed();
1003 fs_uniform.speed = speed;
1004 fs_uniform.planet_size = planet_size;
1005 fs_uniform.show_normals = show_normals ? 1.0 : 0.0;
1006 fs_uniform.show_noise = show_noise ? 1.0 : 0.0;
1007 fs_uniform.seed_value = seed_value;
1008 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(fs_uniform));
1011 host_buffer->Reset();
1014 OpenPlaygroundHere(callback);
1018 using VS = ArrayVertexShader;
1019 using FS = ArrayFragmentShader;
1021 auto context = GetContext();
1022 auto pipeline_descriptor =
1024 ASSERT_TRUE(pipeline_descriptor.has_value());
1026 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
1028 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
1029 ASSERT_TRUE(pipeline && pipeline->IsValid());
1032 context->GetIdleWaiter());
1033 SinglePassCallback callback = [&](
RenderPass& pass) {
1034 auto size = pass.GetRenderTargetSize();
1036 pass.SetPipeline(pipeline);
1037 pass.SetCommandLabel(
"Google Dots");
1040 {
Point(0, size.height)},
1041 {
Point(size.width, 0)},
1042 {
Point(size.width, 0)},
1043 {
Point(0, size.height)},
1044 {
Point(size.width, size.height)}});
1047 VS::FrameInfo frame_info;
1051 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
1053 auto time = GetSecondsElapsed();
1054 auto y_pos = [&time](
float x) {
1055 return 400 + 10 * std::cos(time * 5 +
x / 6);
1058 FS::FragInfo fs_uniform = {
1059 .circle_positions = {
Point(430, y_pos(0)),
Point(480, y_pos(1)),
1066 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(fs_uniform));
1069 host_buffer->Reset();
1072 OpenPlaygroundHere(callback);
1076 using VS = InactiveUniformsVertexShader;
1077 using FS = InactiveUniformsFragmentShader;
1079 auto context = GetContext();
1080 auto pipeline_descriptor =
1082 ASSERT_TRUE(pipeline_descriptor.has_value());
1084 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
1086 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
1087 ASSERT_TRUE(pipeline && pipeline->IsValid());
1090 context->GetIdleWaiter());
1091 SinglePassCallback callback = [&](
RenderPass& pass) {
1092 auto size = pass.GetRenderTargetSize();
1094 pass.SetPipeline(pipeline);
1095 pass.SetCommandLabel(
"Inactive Uniform");
1099 {
Point(0, size.height)},
1100 {
Point(size.width, 0)},
1101 {
Point(size.width, 0)},
1102 {
Point(0, size.height)},
1103 {
Point(size.width, size.height)}});
1106 VS::FrameInfo frame_info;
1110 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
1112 FS::FragInfo fs_uniform = {.unused_color =
Color::Red(),
1114 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(fs_uniform));
1117 host_buffer->Reset();
1120 OpenPlaygroundHere(callback);
1124 using VS = BoxFadeVertexShader;
1134 using VS = BoxFadeVertexShader;
1143 using VS = BoxFadeVertexShader;
1147 {{100, 100, 0.0}, {0.0, 0.0}},
1148 {{800, 100, 0.0}, {1.0, 0.0}},
1149 {{800, 800, 0.0}, {1.0, 1.0}},
1150 {{100, 800, 0.0}, {0.0, 1.0}},
1166 labels_.push_back(
"Never");
1168 labels_.push_back(
"Always");
1170 labels_.push_back(
"Less");
1172 labels_.push_back(
"Equal");
1174 labels_.push_back(
"LessEqual");
1176 labels_.push_back(
"Greater");
1178 labels_.push_back(
"NotEqual");
1180 labels_.push_back(
"GreaterEqual");
1182 assert(labels_.size() == functions_.size());
1185 const char*
const*
labels()
const {
return &labels_[0]; }
1187 int size()
const {
return labels_.size(); }
1190 for (
size_t i = 0; i < functions_.size(); i++) {
1191 if (functions_[i] == func) {
1202 std::vector<const char*> labels_;
1203 std::vector<CompareFunction> functions_;
1212 using VS = BoxFadeVertexShader;
1213 using FS = BoxFadeFragmentShader;
1214 auto context = GetContext();
1215 ASSERT_TRUE(context);
1217 auto desc = BoxFadePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
1218 ASSERT_TRUE(desc.has_value());
1224 {{100, 100, 0.0}, {0.0, 0.0}},
1225 {{800, 100, 0.0}, {1.0, 0.0}},
1226 {{800, 800, 0.0}, {1.0, 1.0}},
1227 {{100, 100, 0.0}, {0.0, 0.0}},
1228 {{800, 800, 0.0}, {1.0, 1.0}},
1229 {{100, 800, 0.0}, {0.0, 1.0}},
1231 auto vertex_buffer =
1233 ASSERT_TRUE(vertex_buffer);
1236 desc->SetStencilAttachmentDescriptors(std::nullopt);
1238 auto bridge = CreateTextureForFixture(
"bay_bridge.jpg");
1239 auto boston = CreateTextureForFixture(
"boston.jpg");
1240 ASSERT_TRUE(bridge && boston);
1242 ASSERT_TRUE(sampler);
1244 static bool mirror =
false;
1245 static int stencil_reference_write = 0xFF;
1246 static int stencil_reference_read = 0x1;
1247 std::vector<uint8_t> stencil_contents;
1248 static int last_stencil_contents_reference_value = 0;
1249 static int current_front_compare =
1251 static int current_back_compare =
1255 context->GetIdleWaiter());
1257 auto buffer = context->CreateCommandBuffer();
1261 buffer->SetLabel(
"Playground Command Buffer");
1269 render_target.SetupDepthStencilAttachments(
1270 *context, *context->GetResourceAllocator(),
1271 render_target.GetRenderTargetSize(),
true,
"stencil", stencil_config);
1273 const auto target_width = render_target.GetRenderTargetSize().width;
1274 const auto target_height = render_target.GetRenderTargetSize().height;
1275 const size_t target_size = target_width * target_height;
1276 if (stencil_contents.size() != target_size ||
1277 last_stencil_contents_reference_value != stencil_reference_write) {
1278 stencil_contents.resize(target_size);
1279 last_stencil_contents_reference_value = stencil_reference_write;
1280 for (
int y = 0; y < target_height; y++) {
1281 for (
int x = 0;
x < target_width;
x++) {
1282 const auto index = y * target_width +
x;
1283 const auto kCheckSize = 64;
1285 (((y / kCheckSize) + (
x / kCheckSize)) % 2 == 0) *
1286 stencil_reference_write;
1287 stencil_contents[index] =
value;
1291 if (!render_target.GetStencilAttachment()->texture->SetContents(
1292 stencil_contents.data(), stencil_contents.size(), 0,
false)) {
1293 VALIDATION_LOG <<
"Could not upload stencil contents to device memory";
1296 auto pass = buffer->CreateRenderPass(render_target);
1300 pass->SetLabel(
"Stencil Buffer");
1301 ImGui::Begin(
"Controls",
nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1302 ImGui::SliderInt(
"Stencil Write Value", &stencil_reference_write, 0,
1304 ImGui::SliderInt(
"Stencil Compare Value", &stencil_reference_read, 0,
1306 ImGui::Checkbox(
"Back face mode", &mirror);
1307 ImGui::ListBox(
"Front face compare function", ¤t_front_compare,
1309 ImGui::ListBox(
"Back face compare function", ¤t_back_compare,
1319 desc->SetStencilAttachmentDescriptors(front, back);
1320 auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get();
1322 assert(pipeline && pipeline->IsValid());
1324 pass->SetCommandLabel(
"Box");
1325 pass->SetPipeline(pipeline);
1326 pass->SetStencilReference(stencil_reference_read);
1327 pass->SetVertexBuffer(vertex_buffer);
1329 VS::UniformBuffer uniforms;
1330 EXPECT_EQ(pass->GetOrthographicTransform(),
1332 uniforms.mvp = pass->GetOrthographicTransform() *
1337 VS::BindUniformBuffer(*pass, host_buffer->EmplaceUniform(uniforms));
1339 FS::FrameInfo frame_info;
1340 frame_info.current_time = GetSecondsElapsed();
1341 frame_info.cursor_position = GetCursorPosition();
1342 frame_info.window_size.x = GetWindowSize().width;
1343 frame_info.window_size.y = GetWindowSize().height;
1345 FS::BindFrameInfo(*pass, host_buffer->EmplaceUniform(frame_info));
1346 FS::BindContents1(*pass, boston, sampler);
1347 FS::BindContents2(*pass, bridge, sampler);
1348 if (!pass->Draw().ok()) {
1351 pass->EncodeCommands();
1354 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
1357 host_buffer->Reset();
1360 OpenPlaygroundHere(callback);
1364 auto context = GetContext();
1365 auto cmd_buffer = context->CreateCommandBuffer();
1366 auto render_target_cache = std::make_shared<RenderTargetAllocator>(
1367 GetContext()->GetResourceAllocator());
1369 auto render_target = render_target_cache->CreateOffscreen(
1370 *context, {100, 100}, 1);
1371 auto render_pass = cmd_buffer->CreateRenderPass(render_target);
1373 EXPECT_EQ(render_pass->GetSampleCount(), render_target.GetSampleCount());
1374 EXPECT_EQ(render_pass->GetRenderTargetPixelFormat(),
1375 render_target.GetRenderTargetPixelFormat());
1376 EXPECT_EQ(render_pass->HasStencilAttachment(),
1377 render_target.GetStencilAttachment().has_value());
1378 EXPECT_EQ(render_pass->GetRenderTargetSize(),
1379 render_target.GetRenderTargetSize());
1380 render_pass->EncodeCommands();
1384 RenderTargetCreateOffscreenMSAASetsDefaultDepthStencilFormat) {
1385 auto context = GetContext();
1386 auto render_target_cache = std::make_shared<RenderTargetAllocator>(
1387 GetContext()->GetResourceAllocator());
1389 RenderTarget render_target = render_target_cache->CreateOffscreenMSAA(
1390 *context, {100, 100}, 1);
1392 ->texture->GetTextureDescriptor()
1394 GetContext()->GetCapabilities()->GetDefaultDepthStencilFormat());
1397 template <
class VertexShader,
class FragmentShader>
1399 const std::shared_ptr<Context>& context) {
1401 auto pipeline_desc =
1402 TexturePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
1403 if (!pipeline_desc.has_value()) {
1407 pipeline_desc->SetStencilAttachmentDescriptors(std::nullopt);
1409 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
1410 if (!pipeline || !pipeline->IsValid()) {
1418 using TextureVS = TextureVertexShader;
1419 using TextureFS = TextureFragmentShader;
1421 using SepiaVS = SepiaVertexShader;
1422 using SepiaFS = SepiaFragmentShader;
1424 auto context = GetContext();
1425 ASSERT_TRUE(context);
1427 if (!context->GetCapabilities()->SupportsFramebufferFetch()) {
1428 GTEST_SKIP() <<
"This test uses framebuffer fetch and the backend doesn't "
1434 auto texture_pipeline = CreateDefaultPipeline<TextureVS, TextureFS>(context);
1435 auto sepia_pipeline = CreateDefaultPipeline<SepiaVS, SepiaFS>(context);
1437 ASSERT_TRUE(texture_pipeline);
1438 ASSERT_TRUE(sepia_pipeline);
1443 {{100, 100, 0.0}, {0.0, 0.0}},
1444 {{800, 100, 0.0}, {1.0, 0.0}},
1445 {{800, 800, 0.0}, {1.0, 1.0}},
1446 {{100, 100, 0.0}, {0.0, 0.0}},
1447 {{800, 800, 0.0}, {1.0, 1.0}},
1448 {{100, 800, 0.0}, {0.0, 1.0}},
1461 auto boston = CreateTextureForFixture(
"boston.jpg");
1462 ASSERT_TRUE(boston);
1464 const auto& sampler = context->GetSamplerLibrary()->GetSampler({});
1465 ASSERT_TRUE(sampler);
1467 SinglePassCallback callback = [&](
RenderPass& pass) {
1469 context->GetIdleWaiter());
1473 pass.SetPipeline(texture_pipeline);
1475 *context->GetResourceAllocator()));
1476 TextureVS::UniformBuffer uniforms;
1479 TextureVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1480 TextureFS::BindTextureContents(pass, boston, sampler);
1481 if (!pass.Draw().ok()) {
1488 pass.SetPipeline(sepia_pipeline);
1490 *context->GetResourceAllocator()));
1491 SepiaVS::UniformBuffer uniforms;
1494 SepiaVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1495 if (!pass.Draw().ok()) {
1502 OpenPlaygroundHere(callback);
1507 using TextureVS = TextureVertexShader;
1508 using TextureFS = TextureFragmentShader;
1510 using SwizzleVS = SepiaVertexShader;
1511 using SwizzleFS = SwizzleFragmentShader;
1513 using SepiaVS = SepiaVertexShader;
1514 using SepiaFS = SepiaFragmentShader;
1516 auto context = GetContext();
1517 ASSERT_TRUE(context);
1519 if (!context->GetCapabilities()->SupportsFramebufferFetch()) {
1520 GTEST_SKIP() <<
"This test uses framebuffer fetch and the backend doesn't "
1526 auto texture_pipeline = CreateDefaultPipeline<TextureVS, TextureFS>(context);
1527 auto swizzle_pipeline = CreateDefaultPipeline<SwizzleVS, SwizzleFS>(context);
1528 auto sepia_pipeline = CreateDefaultPipeline<SepiaVS, SepiaFS>(context);
1530 ASSERT_TRUE(texture_pipeline);
1531 ASSERT_TRUE(swizzle_pipeline);
1532 ASSERT_TRUE(sepia_pipeline);
1537 {{100, 100, 0.0}, {0.0, 0.0}},
1538 {{800, 100, 0.0}, {1.0, 0.0}},
1539 {{800, 800, 0.0}, {1.0, 1.0}},
1540 {{100, 100, 0.0}, {0.0, 0.0}},
1541 {{800, 800, 0.0}, {1.0, 1.0}},
1542 {{100, 800, 0.0}, {0.0, 1.0}},
1555 auto boston = CreateTextureForFixture(
"boston.jpg");
1556 ASSERT_TRUE(boston);
1558 const auto& sampler = context->GetSamplerLibrary()->GetSampler({});
1559 ASSERT_TRUE(sampler);
1561 SinglePassCallback callback = [&](
RenderPass& pass) {
1563 context->GetIdleWaiter());
1567 pass.SetPipeline(texture_pipeline);
1569 *context->GetResourceAllocator()));
1570 TextureVS::UniformBuffer uniforms;
1573 TextureVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1574 TextureFS::BindTextureContents(pass, boston, sampler);
1575 if (!pass.Draw().ok()) {
1582 pass.SetPipeline(sepia_pipeline);
1584 *context->GetResourceAllocator()));
1585 SepiaVS::UniformBuffer uniforms;
1588 SepiaVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1589 if (!pass.Draw().ok()) {
1596 pass.SetPipeline(swizzle_pipeline);
1598 *context->GetResourceAllocator()));
1599 SwizzleVS::UniformBuffer uniforms;
1602 SwizzleVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1603 if (!pass.Draw().ok()) {
1610 OpenPlaygroundHere(callback);
1614 using FS = BoxFadeFragmentShader;
1616 auto context = GetContext();
1618 auto command_buffer = context->CreateCommandBuffer();
1623 auto pass = command_buffer->CreateRenderPass(target);
1624 EXPECT_FALSE(FS::BindContents2(*pass,
nullptr, sampler));
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)
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...
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 &host_buffer) const
size_t GetVertexCount() const
size_t GetIndexCount() const
VertexBufferBuilder & AddVertices(std::initializer_list< VertexType_ > vertices)
void SetLabel(const std::string &label)
constexpr impeller::IndexType GetIndexType() const
VertexBufferBuilder & AppendIndex(IndexType_ index)
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
std::shared_ptr< Pipeline< PipelineDescriptor > > CreateDefaultPipeline(const std::shared_ptr< Context > &context)
PlaygroundTest RendererTest
static const CompareFunctionUIData & CompareFunctionUI()
TEST_P(AiksTest, DrawAtlasNoColor)
INSTANTIATE_PLAYGROUND_SUITE(AiksTest)
@ 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
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.
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 Yellow()
static constexpr Color Blue()
static constexpr Color Green()
static constexpr Matrix MakeOrthographic(TSize< T > size)
static constexpr Matrix MakeTranslation(const Vector3 &t)
static constexpr Matrix MakePerspective(Radians fov_y, Scalar aspect_ratio, Scalar z_near, Scalar z_far)
static Matrix MakeRotationY(Radians r)
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...
std::shared_ptr< const fml::Mapping > data