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"
43 #include "third_party/imgui/imgui.h"
55 using VS = BoxFadeVertexShader;
56 using FS = BoxFadeFragmentShader;
57 auto context = GetContext();
60 auto desc = BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
61 ASSERT_TRUE(desc.has_value());
63 desc->SetStencilAttachmentDescriptors(std::nullopt);
69 {{100, 100, 0.0}, {0.0, 0.0}},
70 {{800, 100, 0.0}, {1.0, 0.0}},
71 {{800, 800, 0.0}, {1.0, 1.0}},
72 {{100, 100, 0.0}, {0.0, 0.0}},
73 {{800, 800, 0.0}, {1.0, 1.0}},
74 {{100, 800, 0.0}, {0.0, 1.0}},
76 auto bridge = CreateTextureForFixture(
"bay_bridge.jpg");
77 auto boston = CreateTextureForFixture(
"boston.jpg");
78 ASSERT_TRUE(bridge && boston);
79 const std::unique_ptr<const Sampler>& sampler =
80 context->GetSamplerLibrary()->GetSampler({});
84 SinglePassCallback callback = [&](
RenderPass& pass) {
85 ImGui::Begin(
"Controls",
nullptr, ImGuiWindowFlags_AlwaysAutoResize);
86 static bool wireframe;
87 ImGui::Checkbox(
"Wireframe", &wireframe);
91 auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get();
93 assert(pipeline && pipeline->IsValid());
95 pass.SetCommandLabel(
"Box");
96 pass.SetPipeline(pipeline);
100 VS::UniformBuffer uniforms;
101 EXPECT_EQ(pass.GetOrthographicTransform(),
105 VS::BindUniformBuffer(pass, host_buffer->EmplaceUniform(uniforms));
107 FS::FrameInfo frame_info;
108 frame_info.current_time = GetSecondsElapsed();
109 frame_info.cursor_position = GetCursorPosition();
110 frame_info.window_size.x = GetWindowSize().width;
111 frame_info.window_size.y = GetWindowSize().height;
113 FS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
114 FS::BindContents1(pass, boston, sampler);
115 FS::BindContents2(pass, bridge, sampler);
117 host_buffer->Reset();
118 return pass.Draw().ok();
120 OpenPlaygroundHere(callback);
124 auto context = GetContext();
125 ASSERT_TRUE(context);
128 using VS = BabyVertexShader;
129 using FS = BabyFragmentShader;
137 ASSERT_TRUE(desc.has_value());
141 desc->SetStencilAttachmentDescriptors(std::nullopt);
145 auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get();
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 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(frag_info));
171 return pass.Draw().ok();
173 OpenPlaygroundHere(callback);
177 using VS = ColorsVertexShader;
178 using FS = ColorsFragmentShader;
179 auto context = GetContext();
180 ASSERT_TRUE(context);
182 ASSERT_TRUE(desc.has_value());
186 desc->SetStencilAttachmentDescriptors(std::nullopt);
188 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
189 ASSERT_TRUE(pipeline);
192 VS::PerVertexData vertices[8] = {
204 uint16_t indices[36] = {
216 auto device_buffer = context->GetResourceAllocator()->CreateBufferWithCopy(
217 reinterpret_cast<uint8_t*
>(&cube),
sizeof(cube));
220 .range =
Range(offsetof(Cube, vertices),
sizeof(Cube::vertices))};
223 .range =
Range(offsetof(Cube, indices),
sizeof(Cube::indices))};
228 const std::unique_ptr<const Sampler>& sampler =
229 context->GetSamplerLibrary()->GetSampler({});
230 ASSERT_TRUE(sampler);
234 SinglePassCallback callback = [&](
RenderPass& pass) {
238 ImGui::Begin(
"Controls",
nullptr, ImGuiWindowFlags_AlwaysAutoResize);
239 ImGui::SliderFloat(
"Field of view", &fov_y.
degrees, 0, 180);
240 ImGui::SliderFloat(
"Camera distance", &
distance, 0, 30);
243 pass.SetCommandLabel(
"Perspective Cube");
244 pass.SetPipeline(pipeline);
245 pass.SetVertexBuffer(vertex_buffer);
247 VS::UniformBuffer uniforms;
248 Scalar time = GetSecondsElapsed();
249 euler_angles =
Vector3(0.19 * time, 0.7 * time, 0.43 * time);
257 VS::BindUniformBuffer(pass, host_buffer->EmplaceUniform(uniforms));
259 host_buffer->Reset();
260 return pass.Draw().ok();
262 OpenPlaygroundHere(callback);
266 using VS = BoxFadeVertexShader;
267 using FS = BoxFadeFragmentShader;
268 auto context = GetContext();
269 ASSERT_TRUE(context);
271 auto desc = BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
272 ASSERT_TRUE(desc.has_value());
274 desc->SetStencilAttachmentDescriptors(std::nullopt);
276 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
277 ASSERT_TRUE(box_pipeline);
283 {{100, 100, 0.0}, {0.0, 0.0}},
284 {{800, 100, 0.0}, {1.0, 0.0}},
285 {{800, 800, 0.0}, {1.0, 1.0}},
286 {{100, 100, 0.0}, {0.0, 0.0}},
287 {{800, 800, 0.0}, {1.0, 1.0}},
288 {{100, 800, 0.0}, {0.0, 1.0}},
292 ASSERT_TRUE(vertex_buffer);
294 auto bridge = CreateTextureForFixture(
"bay_bridge.jpg");
295 auto boston = CreateTextureForFixture(
"boston.jpg");
296 ASSERT_TRUE(bridge && boston);
297 const std::unique_ptr<const Sampler>& sampler =
298 context->GetSamplerLibrary()->GetSampler({});
299 ASSERT_TRUE(sampler);
302 SinglePassCallback callback = [&](
RenderPass& pass) {
303 for (
size_t i = 0; i < 1; i++) {
304 for (
size_t j = 0; j < 1; j++) {
305 pass.SetCommandLabel(
"Box");
306 pass.SetPipeline(box_pipeline);
307 pass.SetVertexBuffer(vertex_buffer);
309 FS::FrameInfo frame_info;
310 frame_info.current_time = GetSecondsElapsed();
311 frame_info.cursor_position = GetCursorPosition();
312 frame_info.window_size.x = GetWindowSize().width;
313 frame_info.window_size.y = GetWindowSize().height;
315 FS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
316 FS::BindContents1(pass, boston, sampler);
317 FS::BindContents2(pass, bridge, sampler);
319 VS::UniformBuffer uniforms;
320 EXPECT_EQ(pass.GetOrthographicTransform(),
322 uniforms.mvp = pass.GetOrthographicTransform() *
325 VS::BindUniformBuffer(pass, host_buffer->EmplaceUniform(uniforms));
326 if (!pass.Draw().ok()) {
332 host_buffer->Reset();
335 OpenPlaygroundHere(callback);
339 using VS = BoxFadeVertexShader;
340 using FS = BoxFadeFragmentShader;
341 auto context = GetContext();
342 ASSERT_TRUE(context);
345 BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
347 pipeline_desc->ClearDepthAttachment();
350 ASSERT_TRUE(pipeline_desc.has_value());
352 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
353 ASSERT_TRUE(box_pipeline);
359 {{100, 100, 0.0}, {0.0, 0.0}},
360 {{800, 100, 0.0}, {1.0, 0.0}},
361 {{800, 800, 0.0}, {1.0, 1.0}},
362 {{100, 100, 0.0}, {0.0, 0.0}},
363 {{800, 800, 0.0}, {1.0, 1.0}},
364 {{100, 800, 0.0}, {0.0, 1.0}},
368 ASSERT_TRUE(vertex_buffer);
370 auto bridge = CreateTextureForFixture(
"bay_bridge.jpg");
371 auto boston = CreateTextureForFixture(
"boston.jpg");
372 ASSERT_TRUE(bridge && boston);
373 const std::unique_ptr<const Sampler>& sampler =
374 context->GetSamplerLibrary()->GetSampler({});
375 ASSERT_TRUE(sampler);
377 std::shared_ptr<RenderPass> r2t_pass;
378 auto cmd_buffer = context->CreateCommandBuffer();
379 ASSERT_TRUE(cmd_buffer);
386 ASSERT_NE(pipeline_desc->GetColorAttachmentDescriptor(0u),
nullptr);
387 texture_descriptor.
format =
388 pipeline_desc->GetColorAttachmentDescriptor(0u)->format;
390 texture_descriptor.
size = {400, 400};
395 context->GetResourceAllocator()->CreateTexture(texture_descriptor);
399 color0.
texture->SetLabel(
"r2t_target");
406 stencil_texture_desc.
size = texture_descriptor.
size;
410 context->GetResourceAllocator()->CreateTexture(stencil_texture_desc);
415 r2t_pass = cmd_buffer->CreateRenderPass(r2t_desc);
416 ASSERT_TRUE(r2t_pass && r2t_pass->IsValid());
419 r2t_pass->SetCommandLabel(
"Box");
420 r2t_pass->SetPipeline(box_pipeline);
421 r2t_pass->SetVertexBuffer(vertex_buffer);
423 FS::FrameInfo frame_info;
424 frame_info.current_time = GetSecondsElapsed();
425 frame_info.cursor_position = GetCursorPosition();
426 frame_info.window_size.x = GetWindowSize().width;
427 frame_info.window_size.y = GetWindowSize().height;
429 FS::BindFrameInfo(*r2t_pass, host_buffer->EmplaceUniform(frame_info));
430 FS::BindContents1(*r2t_pass, boston, sampler);
431 FS::BindContents2(*r2t_pass, bridge, sampler);
433 VS::UniformBuffer uniforms;
436 VS::BindUniformBuffer(*r2t_pass, host_buffer->EmplaceUniform(uniforms));
437 ASSERT_TRUE(r2t_pass->Draw().ok());
438 ASSERT_TRUE(r2t_pass->EncodeCommands());
443 GTEST_SKIP_(
"Instancing is not supported on OpenGL.");
445 using VS = InstancedDrawVertexShader;
446 using FS = InstancedDrawFragmentShader;
450 VS::PerVertexData{
Point{10, 10}},
451 VS::PerVertexData{
Point{10, 110}},
452 VS::PerVertexData{
Point{110, 10}},
453 VS::PerVertexData{
Point{10, 110}},
454 VS::PerVertexData{
Point{110, 10}},
455 VS::PerVertexData{
Point{110, 110}},
458 ASSERT_NE(GetContext(),
nullptr);
461 ->GetPipelineLibrary()
465 .SetStencilAttachmentDescriptors(std::nullopt))
468 ASSERT_TRUE(pipeline && pipeline->IsValid());
470 static constexpr
size_t kInstancesCount = 5u;
471 VS::InstanceInfo<kInstancesCount> instances;
472 for (
size_t i = 0; i < kInstancesCount; i++) {
477 ASSERT_TRUE(OpenPlaygroundHere([&](
RenderPass& pass) ->
bool {
481 VS::FrameInfo frame_info;
486 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
487 VS::BindInstanceInfo(pass, host_buffer->EmplaceStorageBuffer(instances));
493 host_buffer->Reset();
500 GTEST_SKIP() <<
"Mipmap test shader not supported on GLES.";
502 auto context = GetContext();
503 ASSERT_TRUE(context);
505 using VS = MipmapsVertexShader;
506 using FS = MipmapsFragmentShader;
508 ASSERT_TRUE(desc.has_value());
510 desc->SetStencilAttachmentDescriptors(std::nullopt);
511 auto mipmaps_pipeline =
512 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
513 ASSERT_TRUE(mipmaps_pipeline);
518 texture_desc.
size = {800, 600};
521 auto texture = context->GetResourceAllocator()->CreateTexture(texture_desc);
522 ASSERT_TRUE(texture);
524 auto bridge = CreateTextureForFixture(
"bay_bridge.jpg");
525 auto boston = CreateTextureForFixture(
"boston.jpg");
526 ASSERT_TRUE(bridge && boston);
527 const std::unique_ptr<const Sampler>& sampler =
528 context->GetSamplerLibrary()->GetSampler({});
529 ASSERT_TRUE(sampler);
534 auto size =
Point(boston->GetSize());
536 {{0, 0}, {0.0, 0.0}},
537 {{size.x, 0}, {1.0, 0.0}},
538 {{size.x, size.y}, {1.0, 1.0}},
539 {{0, 0}, {0.0, 0.0}},
540 {{size.x, size.y}, {1.0, 1.0}},
541 {{0, size.y}, {0.0, 1.0}},
545 ASSERT_TRUE(vertex_buffer);
549 auto buffer = context->CreateCommandBuffer();
553 buffer->SetLabel(
"Playground Command Buffer");
556 auto pass = buffer->CreateBlitPass();
560 pass->SetLabel(
"Playground Blit Pass");
562 if (render_target.GetColorAttachments().empty()) {
567 pass->AddCopy(bridge, texture);
569 if (!pass->EncodeCommands(context->GetResourceAllocator())) {
575 auto pass = buffer->CreateRenderPass(render_target);
579 pass->SetLabel(
"Playground Render Pass");
581 pass->SetCommandLabel(
"Image");
582 pass->SetPipeline(mipmaps_pipeline);
583 pass->SetVertexBuffer(vertex_buffer);
585 VS::FrameInfo frame_info;
586 EXPECT_EQ(pass->GetOrthographicTransform(),
588 frame_info.mvp = pass->GetOrthographicTransform() *
590 VS::BindFrameInfo(*pass, host_buffer->EmplaceUniform(frame_info));
592 FS::FragInfo frag_info;
594 FS::BindFragInfo(*pass, host_buffer->EmplaceUniform(frag_info));
596 auto& sampler = context->GetSamplerLibrary()->GetSampler({});
597 FS::BindTex(*pass, texture, sampler);
601 pass->EncodeCommands();
604 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
607 host_buffer->Reset();
610 OpenPlaygroundHere(callback);
615 GTEST_SKIP() <<
"Mipmap test shader not supported on GLES.";
617 auto context = GetContext();
618 ASSERT_TRUE(context);
620 using VS = MipmapsVertexShader;
621 using FS = MipmapsFragmentShader;
623 ASSERT_TRUE(desc.has_value());
625 desc->SetStencilAttachmentDescriptors(std::nullopt);
626 auto mipmaps_pipeline =
627 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
628 ASSERT_TRUE(mipmaps_pipeline);
630 auto bridge = CreateTextureForFixture(
"bay_bridge.jpg");
631 auto boston = CreateTextureForFixture(
"boston.jpg");
632 ASSERT_TRUE(bridge && boston);
633 const std::unique_ptr<const Sampler>& sampler =
634 context->GetSamplerLibrary()->GetSampler({});
635 ASSERT_TRUE(sampler);
640 texture_desc.
size = bridge->GetTextureDescriptor().size;
646 device_buffer_desc.
size =
647 bridge->GetTextureDescriptor().GetByteSizeOfBaseMipLevel();
649 context->GetResourceAllocator()->CreateBuffer(device_buffer_desc);
654 auto size =
Point(boston->GetSize());
656 {{0, 0}, {0.0, 0.0}},
657 {{size.x, 0}, {1.0, 0.0}},
658 {{size.x, size.y}, {1.0, 1.0}},
659 {{0, 0}, {0.0, 0.0}},
660 {{size.x, size.y}, {1.0, 1.0}},
661 {{0, size.y}, {0.0, 1.0}},
665 ASSERT_TRUE(vertex_buffer);
670 auto buffer = context->CreateCommandBuffer();
674 buffer->SetLabel(
"Playground Command Buffer");
675 auto pass = buffer->CreateBlitPass();
679 pass->SetLabel(
"Playground Blit Pass");
681 if (render_target.GetColorAttachments().empty()) {
686 pass->AddCopy(bridge, device_buffer);
687 pass->EncodeCommands(context->GetResourceAllocator());
689 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
695 auto buffer = context->CreateCommandBuffer();
699 buffer->SetLabel(
"Playground Command Buffer");
701 auto pass = buffer->CreateRenderPass(render_target);
705 pass->SetLabel(
"Playground Render Pass");
707 pass->SetCommandLabel(
"Image");
708 pass->SetPipeline(mipmaps_pipeline);
709 pass->SetVertexBuffer(vertex_buffer);
711 VS::FrameInfo frame_info;
712 EXPECT_EQ(pass->GetOrthographicTransform(),
714 frame_info.mvp = pass->GetOrthographicTransform() *
716 VS::BindFrameInfo(*pass, host_buffer->EmplaceUniform(frame_info));
718 FS::FragInfo frag_info;
720 FS::BindFragInfo(*pass, host_buffer->EmplaceUniform(frag_info));
722 const std::unique_ptr<const Sampler>& sampler =
723 context->GetSamplerLibrary()->GetSampler({});
726 context->GetResourceAllocator()->CreateTexture(texture_desc);
727 if (!texture->SetContents(device_buffer->OnGetContents(),
732 FS::BindTex(*pass, texture, sampler);
736 pass->EncodeCommands();
737 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
741 host_buffer->Reset();
744 OpenPlaygroundHere(callback);
749 GTEST_SKIP() <<
"Mipmap test shader not supported on GLES.";
751 auto context = GetContext();
752 ASSERT_TRUE(context);
754 using VS = MipmapsVertexShader;
755 using FS = MipmapsFragmentShader;
757 ASSERT_TRUE(desc.has_value());
759 desc->SetStencilAttachmentDescriptors(std::nullopt);
760 auto mipmaps_pipeline =
761 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
762 ASSERT_TRUE(mipmaps_pipeline);
764 auto boston = CreateTextureForFixture(
"boston.jpg",
true);
770 auto size =
Point(boston->GetSize());
772 {{0, 0}, {0.0, 0.0}},
773 {{size.x, 0}, {1.0, 0.0}},
774 {{size.x, size.y}, {1.0, 1.0}},
775 {{0, 0}, {0.0, 0.0}},
776 {{size.x, size.y}, {1.0, 1.0}},
777 {{0, size.y}, {0.0, 1.0}},
781 ASSERT_TRUE(vertex_buffer);
783 bool first_frame =
true;
786 const char* mip_filter_names[] = {
"Base",
"Nearest",
"Linear"};
789 const char* min_filter_names[] = {
"Nearest",
"Linear"};
794 static int selected_mip_filter = 1;
795 static int selected_min_filter = 0;
796 static float lod = 4.5;
798 ImGui::Begin(
"Controls",
nullptr, ImGuiWindowFlags_AlwaysAutoResize);
799 ImGui::Combo(
"Mip filter", &selected_mip_filter, mip_filter_names,
800 sizeof(mip_filter_names) /
sizeof(
char*));
801 ImGui::Combo(
"Min filter", &selected_min_filter, min_filter_names,
802 sizeof(min_filter_names) /
sizeof(
char*));
803 ImGui::SliderFloat(
"LOD", &lod, 0, boston->GetMipCount() - 1);
806 auto buffer = context->CreateCommandBuffer();
810 buffer->SetLabel(
"Playground Command Buffer");
813 auto pass = buffer->CreateBlitPass();
817 pass->SetLabel(
"Playground Blit Pass");
819 pass->GenerateMipmap(boston,
"Boston Mipmap");
821 pass->EncodeCommands(context->GetResourceAllocator());
827 auto pass = buffer->CreateRenderPass(render_target);
831 pass->SetLabel(
"Playground Render Pass");
833 pass->SetCommandLabel(
"Image LOD");
834 pass->SetPipeline(mipmaps_pipeline);
835 pass->SetVertexBuffer(vertex_buffer);
837 VS::FrameInfo frame_info;
838 EXPECT_EQ(pass->GetOrthographicTransform(),
840 frame_info.mvp = pass->GetOrthographicTransform() *
842 VS::BindFrameInfo(*pass, host_buffer->EmplaceUniform(frame_info));
844 FS::FragInfo frag_info;
846 FS::BindFragInfo(*pass, host_buffer->EmplaceUniform(frag_info));
849 sampler_desc.
mip_filter = mip_filters[selected_mip_filter];
850 sampler_desc.
min_filter = min_filters[selected_min_filter];
851 const std::unique_ptr<const Sampler>& sampler =
852 context->GetSamplerLibrary()->GetSampler(sampler_desc);
853 FS::BindTex(*pass, boston, sampler);
857 pass->EncodeCommands();
860 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
863 host_buffer->Reset();
866 OpenPlaygroundHere(callback);
870 using VS = ImpellerVertexShader;
871 using FS = ImpellerFragmentShader;
873 auto context = GetContext();
874 auto pipeline_descriptor =
876 ASSERT_TRUE(pipeline_descriptor.has_value());
878 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
880 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
881 ASSERT_TRUE(pipeline && pipeline->IsValid());
883 auto blue_noise = CreateTextureForFixture(
"blue_noise.png");
887 const std::unique_ptr<const Sampler>& noise_sampler =
888 context->GetSamplerLibrary()->GetSampler(noise_sampler_desc);
890 auto cube_map = CreateTextureCubeForFixture(
891 {
"table_mountain_px.png",
"table_mountain_nx.png",
892 "table_mountain_py.png",
"table_mountain_ny.png",
893 "table_mountain_pz.png",
"table_mountain_nz.png"});
894 const std::unique_ptr<const Sampler>& cube_map_sampler =
895 context->GetSamplerLibrary()->GetSampler({});
898 SinglePassCallback callback = [&](
RenderPass& pass) {
899 auto size = pass.GetRenderTargetSize();
901 pass.SetPipeline(pipeline);
902 pass.SetCommandLabel(
"Impeller SDF scene");
905 {
Point(0, size.height)},
906 {
Point(size.width, 0)},
907 {
Point(size.width, 0)},
908 {
Point(0, size.height)},
909 {
Point(size.width, size.height)}});
912 VS::FrameInfo frame_info;
914 frame_info.mvp = pass.GetOrthographicTransform();
915 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
917 FS::FragInfo fs_uniform;
918 fs_uniform.texture_size =
Point(size);
919 fs_uniform.time = GetSecondsElapsed();
920 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(fs_uniform));
921 FS::BindBlueNoise(pass, blue_noise, noise_sampler);
922 FS::BindCubeMap(pass, cube_map, cube_map_sampler);
925 host_buffer->Reset();
928 OpenPlaygroundHere(callback);
932 using VS = PlanetVertexShader;
933 using FS = PlanetFragmentShader;
935 auto context = GetContext();
936 auto pipeline_descriptor =
938 ASSERT_TRUE(pipeline_descriptor.has_value());
940 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
942 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
943 ASSERT_TRUE(pipeline && pipeline->IsValid());
947 SinglePassCallback callback = [&](
RenderPass& pass) {
948 static Scalar speed = 0.1;
949 static Scalar planet_size = 550.0;
950 static bool show_normals =
false;
951 static bool show_noise =
false;
952 static Scalar seed_value = 42.0;
954 auto size = pass.GetRenderTargetSize();
956 ImGui::Begin(
"Controls",
nullptr, ImGuiWindowFlags_AlwaysAutoResize);
957 ImGui::SliderFloat(
"Speed", &speed, 0.0, 10.0);
958 ImGui::SliderFloat(
"Planet Size", &planet_size, 0.1, 1000);
959 ImGui::Checkbox(
"Show Normals", &show_normals);
960 ImGui::Checkbox(
"Show Noise", &show_noise);
961 ImGui::InputFloat(
"Seed Value", &seed_value);
964 pass.SetPipeline(pipeline);
965 pass.SetCommandLabel(
"Planet scene");
968 {
Point(0, size.height)},
969 {
Point(size.width, 0)},
970 {
Point(size.width, 0)},
971 {
Point(0, size.height)},
972 {
Point(size.width, size.height)}});
975 VS::FrameInfo frame_info;
977 frame_info.mvp = pass.GetOrthographicTransform();
978 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
980 FS::FragInfo fs_uniform;
981 fs_uniform.resolution =
Point(size);
982 fs_uniform.time = GetSecondsElapsed();
983 fs_uniform.speed = speed;
984 fs_uniform.planet_size = planet_size;
985 fs_uniform.show_normals = show_normals ? 1.0 : 0.0;
986 fs_uniform.show_noise = show_noise ? 1.0 : 0.0;
987 fs_uniform.seed_value = seed_value;
988 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(fs_uniform));
991 host_buffer->Reset();
994 OpenPlaygroundHere(callback);
998 using VS = ArrayVertexShader;
999 using FS = ArrayFragmentShader;
1001 auto context = GetContext();
1002 auto pipeline_descriptor =
1004 ASSERT_TRUE(pipeline_descriptor.has_value());
1006 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
1008 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
1009 ASSERT_TRUE(pipeline && pipeline->IsValid());
1012 SinglePassCallback callback = [&](
RenderPass& pass) {
1013 auto size = pass.GetRenderTargetSize();
1015 pass.SetPipeline(pipeline);
1016 pass.SetCommandLabel(
"Google Dots");
1019 {
Point(0, size.height)},
1020 {
Point(size.width, 0)},
1021 {
Point(size.width, 0)},
1022 {
Point(0, size.height)},
1023 {
Point(size.width, size.height)}});
1026 VS::FrameInfo frame_info;
1030 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
1032 auto time = GetSecondsElapsed();
1033 auto y_pos = [&time](
float x) {
1034 return 400 + 10 * std::cos(time * 5 + x / 6);
1037 FS::FragInfo fs_uniform = {
1038 .circle_positions = {
Point(430, y_pos(0)),
Point(480, y_pos(1)),
1045 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(fs_uniform));
1048 host_buffer->Reset();
1051 OpenPlaygroundHere(callback);
1055 using VS = InactiveUniformsVertexShader;
1056 using FS = InactiveUniformsFragmentShader;
1058 auto context = GetContext();
1059 auto pipeline_descriptor =
1061 ASSERT_TRUE(pipeline_descriptor.has_value());
1063 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
1065 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
1066 ASSERT_TRUE(pipeline && pipeline->IsValid());
1069 SinglePassCallback callback = [&](
RenderPass& pass) {
1070 auto size = pass.GetRenderTargetSize();
1072 pass.SetPipeline(pipeline);
1073 pass.SetCommandLabel(
"Inactive Uniform");
1077 {
Point(0, size.height)},
1078 {
Point(size.width, 0)},
1079 {
Point(size.width, 0)},
1080 {
Point(0, size.height)},
1081 {
Point(size.width, size.height)}});
1084 VS::FrameInfo frame_info;
1088 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
1090 FS::FragInfo fs_uniform = {.unused_color =
Color::Red(),
1092 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(fs_uniform));
1095 host_buffer->Reset();
1098 OpenPlaygroundHere(callback);
1102 using VS = BoxFadeVertexShader;
1112 using VS = BoxFadeVertexShader;
1121 using VS = BoxFadeVertexShader;
1125 {{100, 100, 0.0}, {0.0, 0.0}},
1126 {{800, 100, 0.0}, {1.0, 0.0}},
1127 {{800, 800, 0.0}, {1.0, 1.0}},
1128 {{100, 800, 0.0}, {0.0, 1.0}},
1144 labels_.push_back(
"Never");
1146 labels_.push_back(
"Always");
1148 labels_.push_back(
"Less");
1150 labels_.push_back(
"Equal");
1152 labels_.push_back(
"LessEqual");
1154 labels_.push_back(
"Greater");
1156 labels_.push_back(
"NotEqual");
1158 labels_.push_back(
"GreaterEqual");
1160 assert(labels_.size() == functions_.size());
1163 const char*
const*
labels()
const {
return &labels_[0]; }
1165 int size()
const {
return labels_.size(); }
1168 for (
size_t i = 0; i < functions_.size(); i++) {
1169 if (functions_[i] == func) {
1180 std::vector<const char*> labels_;
1181 std::vector<CompareFunction> functions_;
1190 using VS = BoxFadeVertexShader;
1191 using FS = BoxFadeFragmentShader;
1192 auto context = GetContext();
1193 ASSERT_TRUE(context);
1195 auto desc = BoxFadePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
1196 ASSERT_TRUE(desc.has_value());
1202 {{100, 100, 0.0}, {0.0, 0.0}},
1203 {{800, 100, 0.0}, {1.0, 0.0}},
1204 {{800, 800, 0.0}, {1.0, 1.0}},
1205 {{100, 100, 0.0}, {0.0, 0.0}},
1206 {{800, 800, 0.0}, {1.0, 1.0}},
1207 {{100, 800, 0.0}, {0.0, 1.0}},
1209 auto vertex_buffer =
1211 ASSERT_TRUE(vertex_buffer);
1214 desc->SetStencilAttachmentDescriptors(std::nullopt);
1216 auto bridge = CreateTextureForFixture(
"bay_bridge.jpg");
1217 auto boston = CreateTextureForFixture(
"boston.jpg");
1218 ASSERT_TRUE(bridge && boston);
1219 const std::unique_ptr<const Sampler>& sampler =
1220 context->GetSamplerLibrary()->GetSampler({});
1221 ASSERT_TRUE(sampler);
1223 static bool mirror =
false;
1224 static int stencil_reference_write = 0xFF;
1225 static int stencil_reference_read = 0x1;
1226 std::vector<uint8_t> stencil_contents;
1227 static int last_stencil_contents_reference_value = 0;
1228 static int current_front_compare =
1230 static int current_back_compare =
1235 auto buffer = context->CreateCommandBuffer();
1239 buffer->SetLabel(
"Playground Command Buffer");
1247 render_target.SetupDepthStencilAttachments(
1248 *context, *context->GetResourceAllocator(),
1249 render_target.GetRenderTargetSize(),
true,
"stencil", stencil_config);
1251 const auto target_width = render_target.GetRenderTargetSize().width;
1252 const auto target_height = render_target.GetRenderTargetSize().height;
1253 const size_t target_size = target_width * target_height;
1254 if (stencil_contents.size() != target_size ||
1255 last_stencil_contents_reference_value != stencil_reference_write) {
1256 stencil_contents.resize(target_size);
1257 last_stencil_contents_reference_value = stencil_reference_write;
1258 for (
int y = 0; y < target_height; y++) {
1259 for (
int x = 0; x < target_width; x++) {
1260 const auto index = y * target_width + x;
1261 const auto kCheckSize = 64;
1263 (((y / kCheckSize) + (x / kCheckSize)) % 2 == 0) *
1264 stencil_reference_write;
1265 stencil_contents[index] = value;
1269 if (!render_target.GetStencilAttachment()->texture->SetContents(
1270 stencil_contents.data(), stencil_contents.size(), 0,
false)) {
1271 VALIDATION_LOG <<
"Could not upload stencil contents to device memory";
1274 auto pass = buffer->CreateRenderPass(render_target);
1278 pass->SetLabel(
"Stencil Buffer");
1279 ImGui::Begin(
"Controls",
nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1280 ImGui::SliderInt(
"Stencil Write Value", &stencil_reference_write, 0,
1282 ImGui::SliderInt(
"Stencil Compare Value", &stencil_reference_read, 0,
1284 ImGui::Checkbox(
"Back face mode", &mirror);
1285 ImGui::ListBox(
"Front face compare function", ¤t_front_compare,
1287 ImGui::ListBox(
"Back face compare function", ¤t_back_compare,
1297 desc->SetStencilAttachmentDescriptors(front, back);
1298 auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get();
1300 assert(pipeline && pipeline->IsValid());
1302 pass->SetCommandLabel(
"Box");
1303 pass->SetPipeline(pipeline);
1304 pass->SetStencilReference(stencil_reference_read);
1305 pass->SetVertexBuffer(vertex_buffer);
1307 VS::UniformBuffer uniforms;
1308 EXPECT_EQ(pass->GetOrthographicTransform(),
1310 uniforms.mvp = pass->GetOrthographicTransform() *
1315 VS::BindUniformBuffer(*pass, host_buffer->EmplaceUniform(uniforms));
1317 FS::FrameInfo frame_info;
1318 frame_info.current_time = GetSecondsElapsed();
1319 frame_info.cursor_position = GetCursorPosition();
1320 frame_info.window_size.x = GetWindowSize().width;
1321 frame_info.window_size.y = GetWindowSize().height;
1323 FS::BindFrameInfo(*pass, host_buffer->EmplaceUniform(frame_info));
1324 FS::BindContents1(*pass, boston, sampler);
1325 FS::BindContents2(*pass, bridge, sampler);
1326 if (!pass->Draw().ok()) {
1329 pass->EncodeCommands();
1332 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
1335 host_buffer->Reset();
1338 OpenPlaygroundHere(callback);
1342 auto context = GetContext();
1343 auto cmd_buffer = context->CreateCommandBuffer();
1344 auto render_target_cache = std::make_shared<RenderTargetAllocator>(
1345 GetContext()->GetResourceAllocator());
1347 auto render_target = render_target_cache->CreateOffscreen(
1348 *context, {100, 100}, 1);
1349 auto render_pass = cmd_buffer->CreateRenderPass(render_target);
1351 EXPECT_EQ(render_pass->GetSampleCount(), render_target.GetSampleCount());
1352 EXPECT_EQ(render_pass->GetRenderTargetPixelFormat(),
1353 render_target.GetRenderTargetPixelFormat());
1354 EXPECT_EQ(render_pass->HasStencilAttachment(),
1355 render_target.GetStencilAttachment().has_value());
1356 EXPECT_EQ(render_pass->GetRenderTargetSize(),
1357 render_target.GetRenderTargetSize());
1358 render_pass->EncodeCommands();
1362 RenderTargetCreateOffscreenMSAASetsDefaultDepthStencilFormat) {
1363 auto context = GetContext();
1364 auto render_target_cache = std::make_shared<RenderTargetAllocator>(
1365 GetContext()->GetResourceAllocator());
1367 RenderTarget render_target = render_target_cache->CreateOffscreenMSAA(
1368 *context, {100, 100}, 1);
1370 ->texture->GetTextureDescriptor()
1372 GetContext()->GetCapabilities()->GetDefaultDepthStencilFormat());
1375 template <
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()) {
1385 pipeline_desc->SetStencilAttachmentDescriptors(std::nullopt);
1387 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
1388 if (!pipeline || !pipeline->IsValid()) {
1399 GTEST_SKIP_(
"Not supported on GLES.");
1403 using TextureVS = TextureVertexShader;
1404 using TextureFS = TextureFragmentShader;
1406 using SepiaVS = SepiaVertexShader;
1407 using SepiaFS = SepiaFragmentShader;
1409 auto context = GetContext();
1410 ASSERT_TRUE(context);
1412 if (!context->GetCapabilities()->SupportsFramebufferFetch()) {
1414 "This test uses framebuffer fetch and the backend doesn't support it.");
1419 auto texture_pipeline = CreateDefaultPipeline<TextureVS, TextureFS>(context);
1420 auto sepia_pipeline = CreateDefaultPipeline<SepiaVS, SepiaFS>(context);
1422 ASSERT_TRUE(texture_pipeline);
1423 ASSERT_TRUE(sepia_pipeline);
1428 {{100, 100, 0.0}, {0.0, 0.0}},
1429 {{800, 100, 0.0}, {1.0, 0.0}},
1430 {{800, 800, 0.0}, {1.0, 1.0}},
1431 {{100, 100, 0.0}, {0.0, 0.0}},
1432 {{800, 800, 0.0}, {1.0, 1.0}},
1433 {{100, 800, 0.0}, {0.0, 1.0}},
1446 auto boston = CreateTextureForFixture(
"boston.jpg");
1447 ASSERT_TRUE(boston);
1449 const auto& sampler = context->GetSamplerLibrary()->GetSampler({});
1450 ASSERT_TRUE(sampler);
1452 SinglePassCallback callback = [&](
RenderPass& pass) {
1457 pass.SetPipeline(texture_pipeline);
1459 *context->GetResourceAllocator()));
1460 TextureVS::UniformBuffer uniforms;
1463 TextureVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1464 TextureFS::BindTextureContents(pass, boston, sampler);
1465 if (!pass.Draw().ok()) {
1472 pass.SetPipeline(sepia_pipeline);
1474 *context->GetResourceAllocator()));
1475 SepiaVS::UniformBuffer uniforms;
1478 SepiaVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1479 if (!pass.Draw().ok()) {
1486 OpenPlaygroundHere(callback);
1494 GTEST_SKIP_(
"Not supported on GLES.");
1498 using TextureVS = TextureVertexShader;
1499 using TextureFS = TextureFragmentShader;
1501 using SwizzleVS = SepiaVertexShader;
1502 using SwizzleFS = SwizzleFragmentShader;
1504 using SepiaVS = SepiaVertexShader;
1505 using SepiaFS = SepiaFragmentShader;
1507 auto context = GetContext();
1508 ASSERT_TRUE(context);
1510 if (!context->GetCapabilities()->SupportsFramebufferFetch()) {
1512 "This test uses framebuffer fetch and the backend doesn't support it.");
1517 auto texture_pipeline = CreateDefaultPipeline<TextureVS, TextureFS>(context);
1518 auto swizzle_pipeline = CreateDefaultPipeline<SwizzleVS, SwizzleFS>(context);
1519 auto sepia_pipeline = CreateDefaultPipeline<SepiaVS, SepiaFS>(context);
1521 ASSERT_TRUE(texture_pipeline);
1522 ASSERT_TRUE(swizzle_pipeline);
1523 ASSERT_TRUE(sepia_pipeline);
1528 {{100, 100, 0.0}, {0.0, 0.0}},
1529 {{800, 100, 0.0}, {1.0, 0.0}},
1530 {{800, 800, 0.0}, {1.0, 1.0}},
1531 {{100, 100, 0.0}, {0.0, 0.0}},
1532 {{800, 800, 0.0}, {1.0, 1.0}},
1533 {{100, 800, 0.0}, {0.0, 1.0}},
1546 auto boston = CreateTextureForFixture(
"boston.jpg");
1547 ASSERT_TRUE(boston);
1549 const auto& sampler = context->GetSamplerLibrary()->GetSampler({});
1550 ASSERT_TRUE(sampler);
1552 SinglePassCallback callback = [&](
RenderPass& pass) {
1557 pass.SetPipeline(texture_pipeline);
1559 *context->GetResourceAllocator()));
1560 TextureVS::UniformBuffer uniforms;
1563 TextureVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1564 TextureFS::BindTextureContents(pass, boston, sampler);
1565 if (!pass.Draw().ok()) {
1572 pass.SetPipeline(sepia_pipeline);
1574 *context->GetResourceAllocator()));
1575 SepiaVS::UniformBuffer uniforms;
1578 SepiaVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1579 if (!pass.Draw().ok()) {
1586 pass.SetPipeline(swizzle_pipeline);
1588 *context->GetResourceAllocator()));
1589 SwizzleVS::UniformBuffer uniforms;
1592 SwizzleVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1593 if (!pass.Draw().ok()) {
1600 OpenPlaygroundHere(callback);