5 #include "flutter/fml/logging.h"
10 #include "impeller/fixtures/array.frag.h"
11 #include "impeller/fixtures/array.vert.h"
12 #include "impeller/fixtures/box_fade.frag.h"
13 #include "impeller/fixtures/box_fade.vert.h"
14 #include "impeller/fixtures/colors.frag.h"
15 #include "impeller/fixtures/colors.vert.h"
16 #include "impeller/fixtures/impeller.frag.h"
17 #include "impeller/fixtures/impeller.vert.h"
18 #include "impeller/fixtures/inactive_uniforms.frag.h"
19 #include "impeller/fixtures/inactive_uniforms.vert.h"
20 #include "impeller/fixtures/instanced_draw.frag.h"
21 #include "impeller/fixtures/instanced_draw.vert.h"
22 #include "impeller/fixtures/mipmaps.frag.h"
23 #include "impeller/fixtures/mipmaps.vert.h"
24 #include "impeller/fixtures/sepia.frag.h"
25 #include "impeller/fixtures/sepia.vert.h"
26 #include "impeller/fixtures/swizzle.frag.h"
27 #include "impeller/fixtures/test_texture.frag.h"
28 #include "impeller/fixtures/test_texture.vert.h"
29 #include "impeller/fixtures/texture.frag.h"
30 #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);
78 const std::unique_ptr<const Sampler>& sampler =
79 context->GetSamplerLibrary()->GetSampler({});
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 using VS = ColorsVertexShader;
124 using FS = ColorsFragmentShader;
125 auto context = GetContext();
126 ASSERT_TRUE(context);
128 ASSERT_TRUE(desc.has_value());
132 desc->SetStencilAttachmentDescriptors(std::nullopt);
134 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
135 ASSERT_TRUE(pipeline);
138 VS::PerVertexData vertices[8] = {
150 uint16_t indices[36] = {
162 auto device_buffer = context->GetResourceAllocator()->CreateBufferWithCopy(
163 reinterpret_cast<uint8_t*
>(&cube),
sizeof(cube));
166 .range =
Range(offsetof(Cube, vertices),
sizeof(Cube::vertices))};
169 .range =
Range(offsetof(Cube, indices),
sizeof(Cube::indices))};
174 const std::unique_ptr<const Sampler>& sampler =
175 context->GetSamplerLibrary()->GetSampler({});
176 ASSERT_TRUE(sampler);
180 SinglePassCallback callback = [&](
RenderPass& pass) {
184 ImGui::Begin(
"Controls",
nullptr, ImGuiWindowFlags_AlwaysAutoResize);
185 ImGui::SliderFloat(
"Field of view", &fov_y.
degrees, 0, 180);
186 ImGui::SliderFloat(
"Camera distance", &
distance, 0, 30);
189 pass.SetCommandLabel(
"Perspective Cube");
190 pass.SetPipeline(pipeline);
191 pass.SetVertexBuffer(vertex_buffer);
193 VS::UniformBuffer uniforms;
194 Scalar time = GetSecondsElapsed();
195 euler_angles =
Vector3(0.19 * time, 0.7 * time, 0.43 * time);
203 VS::BindUniformBuffer(pass, host_buffer->EmplaceUniform(uniforms));
205 host_buffer->Reset();
206 return pass.Draw().ok();
208 OpenPlaygroundHere(callback);
212 using VS = BoxFadeVertexShader;
213 using FS = BoxFadeFragmentShader;
214 auto context = GetContext();
215 ASSERT_TRUE(context);
217 auto desc = BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
218 ASSERT_TRUE(desc.has_value());
220 desc->SetStencilAttachmentDescriptors(std::nullopt);
222 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
223 ASSERT_TRUE(box_pipeline);
229 {{100, 100, 0.0}, {0.0, 0.0}},
230 {{800, 100, 0.0}, {1.0, 0.0}},
231 {{800, 800, 0.0}, {1.0, 1.0}},
232 {{100, 100, 0.0}, {0.0, 0.0}},
233 {{800, 800, 0.0}, {1.0, 1.0}},
234 {{100, 800, 0.0}, {0.0, 1.0}},
238 ASSERT_TRUE(vertex_buffer);
240 auto bridge = CreateTextureForFixture(
"bay_bridge.jpg");
241 auto boston = CreateTextureForFixture(
"boston.jpg");
242 ASSERT_TRUE(bridge && boston);
243 const std::unique_ptr<const Sampler>& sampler =
244 context->GetSamplerLibrary()->GetSampler({});
245 ASSERT_TRUE(sampler);
248 SinglePassCallback callback = [&](
RenderPass& pass) {
249 for (
size_t i = 0; i < 1; i++) {
250 for (
size_t j = 0; j < 1; j++) {
251 pass.SetCommandLabel(
"Box");
252 pass.SetPipeline(box_pipeline);
253 pass.SetVertexBuffer(vertex_buffer);
255 FS::FrameInfo frame_info;
256 frame_info.current_time = GetSecondsElapsed();
257 frame_info.cursor_position = GetCursorPosition();
258 frame_info.window_size.x = GetWindowSize().width;
259 frame_info.window_size.y = GetWindowSize().height;
261 FS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
262 FS::BindContents1(pass, boston, sampler);
263 FS::BindContents2(pass, bridge, sampler);
265 VS::UniformBuffer uniforms;
266 EXPECT_EQ(pass.GetOrthographicTransform(),
268 uniforms.mvp = pass.GetOrthographicTransform() *
271 VS::BindUniformBuffer(pass, host_buffer->EmplaceUniform(uniforms));
272 if (!pass.Draw().ok()) {
278 host_buffer->Reset();
281 OpenPlaygroundHere(callback);
285 using VS = BoxFadeVertexShader;
286 using FS = BoxFadeFragmentShader;
287 auto context = GetContext();
288 ASSERT_TRUE(context);
291 BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
293 pipeline_desc->ClearDepthAttachment();
296 ASSERT_TRUE(pipeline_desc.has_value());
298 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
299 ASSERT_TRUE(box_pipeline);
305 {{100, 100, 0.0}, {0.0, 0.0}},
306 {{800, 100, 0.0}, {1.0, 0.0}},
307 {{800, 800, 0.0}, {1.0, 1.0}},
308 {{100, 100, 0.0}, {0.0, 0.0}},
309 {{800, 800, 0.0}, {1.0, 1.0}},
310 {{100, 800, 0.0}, {0.0, 1.0}},
314 ASSERT_TRUE(vertex_buffer);
316 auto bridge = CreateTextureForFixture(
"bay_bridge.jpg");
317 auto boston = CreateTextureForFixture(
"boston.jpg");
318 ASSERT_TRUE(bridge && boston);
319 const std::unique_ptr<const Sampler>& sampler =
320 context->GetSamplerLibrary()->GetSampler({});
321 ASSERT_TRUE(sampler);
323 std::shared_ptr<RenderPass> r2t_pass;
324 auto cmd_buffer = context->CreateCommandBuffer();
325 ASSERT_TRUE(cmd_buffer);
332 ASSERT_NE(pipeline_desc->GetColorAttachmentDescriptor(0u),
nullptr);
333 texture_descriptor.
format =
334 pipeline_desc->GetColorAttachmentDescriptor(0u)->format;
336 texture_descriptor.
size = {400, 400};
341 context->GetResourceAllocator()->CreateTexture(texture_descriptor);
345 color0.
texture->SetLabel(
"r2t_target");
352 stencil_texture_desc.
size = texture_descriptor.
size;
356 context->GetResourceAllocator()->CreateTexture(stencil_texture_desc);
361 r2t_pass = cmd_buffer->CreateRenderPass(r2t_desc);
362 ASSERT_TRUE(r2t_pass && r2t_pass->IsValid());
365 r2t_pass->SetCommandLabel(
"Box");
366 r2t_pass->SetPipeline(box_pipeline);
367 r2t_pass->SetVertexBuffer(vertex_buffer);
369 FS::FrameInfo frame_info;
370 frame_info.current_time = GetSecondsElapsed();
371 frame_info.cursor_position = GetCursorPosition();
372 frame_info.window_size.x = GetWindowSize().width;
373 frame_info.window_size.y = GetWindowSize().height;
375 FS::BindFrameInfo(*r2t_pass, host_buffer->EmplaceUniform(frame_info));
376 FS::BindContents1(*r2t_pass, boston, sampler);
377 FS::BindContents2(*r2t_pass, bridge, sampler);
379 VS::UniformBuffer uniforms;
382 VS::BindUniformBuffer(*r2t_pass, host_buffer->EmplaceUniform(uniforms));
383 ASSERT_TRUE(r2t_pass->Draw().ok());
384 ASSERT_TRUE(r2t_pass->EncodeCommands());
389 GTEST_SKIP_(
"Instancing is not supported on OpenGL.");
391 using VS = InstancedDrawVertexShader;
392 using FS = InstancedDrawFragmentShader;
402 [&builder](
const float* vertices,
size_t vertices_count,
403 const uint16_t* indices,
size_t indices_count) {
404 for (
auto i = 0u; i < vertices_count * 2; i += 2) {
405 VS::PerVertexData data;
406 data.vtx = {vertices[i], vertices[i + 1]};
409 for (
auto i = 0u; i < indices_count; i++) {
415 ASSERT_NE(GetContext(),
nullptr);
418 ->GetPipelineLibrary()
422 .SetStencilAttachmentDescriptors(std::nullopt))
425 ASSERT_TRUE(pipeline && pipeline->IsValid());
427 static constexpr
size_t kInstancesCount = 5u;
428 VS::InstanceInfo<kInstancesCount> instances;
429 for (
size_t i = 0; i < kInstancesCount; i++) {
434 ASSERT_TRUE(OpenPlaygroundHere([&](
RenderPass& pass) ->
bool {
438 VS::FrameInfo frame_info;
443 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
444 VS::BindInstanceInfo(pass, host_buffer->EmplaceStorageBuffer(instances));
450 host_buffer->Reset();
457 GTEST_SKIP() <<
"Mipmap test shader not supported on GLES.";
459 auto context = GetContext();
460 ASSERT_TRUE(context);
462 using VS = MipmapsVertexShader;
463 using FS = MipmapsFragmentShader;
465 ASSERT_TRUE(desc.has_value());
467 desc->SetStencilAttachmentDescriptors(std::nullopt);
468 auto mipmaps_pipeline =
469 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
470 ASSERT_TRUE(mipmaps_pipeline);
475 texture_desc.
size = {800, 600};
478 auto texture = context->GetResourceAllocator()->CreateTexture(texture_desc);
479 ASSERT_TRUE(texture);
481 auto bridge = CreateTextureForFixture(
"bay_bridge.jpg");
482 auto boston = CreateTextureForFixture(
"boston.jpg");
483 ASSERT_TRUE(bridge && boston);
484 const std::unique_ptr<const Sampler>& sampler =
485 context->GetSamplerLibrary()->GetSampler({});
486 ASSERT_TRUE(sampler);
491 auto size =
Point(boston->GetSize());
493 {{0, 0}, {0.0, 0.0}},
494 {{size.x, 0}, {1.0, 0.0}},
495 {{size.x, size.y}, {1.0, 1.0}},
496 {{0, 0}, {0.0, 0.0}},
497 {{size.x, size.y}, {1.0, 1.0}},
498 {{0, size.y}, {0.0, 1.0}},
502 ASSERT_TRUE(vertex_buffer);
506 auto buffer = context->CreateCommandBuffer();
510 buffer->SetLabel(
"Playground Command Buffer");
513 auto pass = buffer->CreateBlitPass();
517 pass->SetLabel(
"Playground Blit Pass");
519 if (render_target.GetColorAttachments().empty()) {
524 pass->AddCopy(bridge, texture);
526 if (!pass->EncodeCommands(context->GetResourceAllocator())) {
532 auto pass = buffer->CreateRenderPass(render_target);
536 pass->SetLabel(
"Playground Render Pass");
538 pass->SetCommandLabel(
"Image");
539 pass->SetPipeline(mipmaps_pipeline);
540 pass->SetVertexBuffer(vertex_buffer);
542 VS::FrameInfo frame_info;
543 EXPECT_EQ(pass->GetOrthographicTransform(),
545 frame_info.mvp = pass->GetOrthographicTransform() *
547 VS::BindFrameInfo(*pass, host_buffer->EmplaceUniform(frame_info));
549 FS::FragInfo frag_info;
551 FS::BindFragInfo(*pass, host_buffer->EmplaceUniform(frag_info));
553 auto& sampler = context->GetSamplerLibrary()->GetSampler({});
554 FS::BindTex(*pass, texture, sampler);
558 pass->EncodeCommands();
561 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
564 host_buffer->Reset();
567 OpenPlaygroundHere(callback);
572 GTEST_SKIP() <<
"Mipmap test shader not supported on GLES.";
574 auto context = GetContext();
575 ASSERT_TRUE(context);
577 using VS = MipmapsVertexShader;
578 using FS = MipmapsFragmentShader;
580 ASSERT_TRUE(desc.has_value());
582 desc->SetStencilAttachmentDescriptors(std::nullopt);
583 auto mipmaps_pipeline =
584 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
585 ASSERT_TRUE(mipmaps_pipeline);
587 auto bridge = CreateTextureForFixture(
"bay_bridge.jpg");
588 auto boston = CreateTextureForFixture(
"boston.jpg");
589 ASSERT_TRUE(bridge && boston);
590 const std::unique_ptr<const Sampler>& sampler =
591 context->GetSamplerLibrary()->GetSampler({});
592 ASSERT_TRUE(sampler);
597 texture_desc.
size = bridge->GetTextureDescriptor().size;
603 device_buffer_desc.
size =
604 bridge->GetTextureDescriptor().GetByteSizeOfBaseMipLevel();
606 context->GetResourceAllocator()->CreateBuffer(device_buffer_desc);
611 auto size =
Point(boston->GetSize());
613 {{0, 0}, {0.0, 0.0}},
614 {{size.x, 0}, {1.0, 0.0}},
615 {{size.x, size.y}, {1.0, 1.0}},
616 {{0, 0}, {0.0, 0.0}},
617 {{size.x, size.y}, {1.0, 1.0}},
618 {{0, size.y}, {0.0, 1.0}},
622 ASSERT_TRUE(vertex_buffer);
627 auto buffer = context->CreateCommandBuffer();
631 buffer->SetLabel(
"Playground Command Buffer");
632 auto pass = buffer->CreateBlitPass();
636 pass->SetLabel(
"Playground Blit Pass");
638 if (render_target.GetColorAttachments().empty()) {
643 pass->AddCopy(bridge, device_buffer);
644 pass->EncodeCommands(context->GetResourceAllocator());
646 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
652 auto buffer = context->CreateCommandBuffer();
656 buffer->SetLabel(
"Playground Command Buffer");
658 auto pass = buffer->CreateRenderPass(render_target);
662 pass->SetLabel(
"Playground Render Pass");
664 pass->SetCommandLabel(
"Image");
665 pass->SetPipeline(mipmaps_pipeline);
666 pass->SetVertexBuffer(vertex_buffer);
668 VS::FrameInfo frame_info;
669 EXPECT_EQ(pass->GetOrthographicTransform(),
671 frame_info.mvp = pass->GetOrthographicTransform() *
673 VS::BindFrameInfo(*pass, host_buffer->EmplaceUniform(frame_info));
675 FS::FragInfo frag_info;
677 FS::BindFragInfo(*pass, host_buffer->EmplaceUniform(frag_info));
679 const std::unique_ptr<const Sampler>& sampler =
680 context->GetSamplerLibrary()->GetSampler({});
683 context->GetResourceAllocator()->CreateTexture(texture_desc);
684 if (!texture->SetContents(device_buffer->OnGetContents(),
685 buffer_view.range.length)) {
689 FS::BindTex(*pass, texture, sampler);
693 pass->EncodeCommands();
694 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
698 host_buffer->Reset();
701 OpenPlaygroundHere(callback);
706 GTEST_SKIP() <<
"Mipmap test shader not supported on GLES.";
708 auto context = GetContext();
709 ASSERT_TRUE(context);
711 using VS = MipmapsVertexShader;
712 using FS = MipmapsFragmentShader;
714 ASSERT_TRUE(desc.has_value());
716 desc->SetStencilAttachmentDescriptors(std::nullopt);
717 auto mipmaps_pipeline =
718 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
719 ASSERT_TRUE(mipmaps_pipeline);
721 auto boston = CreateTextureForFixture(
"boston.jpg",
true);
727 auto size =
Point(boston->GetSize());
729 {{0, 0}, {0.0, 0.0}},
730 {{size.x, 0}, {1.0, 0.0}},
731 {{size.x, size.y}, {1.0, 1.0}},
732 {{0, 0}, {0.0, 0.0}},
733 {{size.x, size.y}, {1.0, 1.0}},
734 {{0, size.y}, {0.0, 1.0}},
738 ASSERT_TRUE(vertex_buffer);
740 bool first_frame =
true;
743 const char* mip_filter_names[] = {
"Nearest",
"Linear"};
745 const char* min_filter_names[] = {
"Nearest",
"Linear"};
750 static int selected_mip_filter = 1;
751 static int selected_min_filter = 0;
752 static float lod = 4.5;
754 ImGui::Begin(
"Controls",
nullptr, ImGuiWindowFlags_AlwaysAutoResize);
755 ImGui::Combo(
"Mip filter", &selected_mip_filter, mip_filter_names,
756 sizeof(mip_filter_names) /
sizeof(
char*));
757 ImGui::Combo(
"Min filter", &selected_min_filter, min_filter_names,
758 sizeof(min_filter_names) /
sizeof(
char*));
759 ImGui::SliderFloat(
"LOD", &lod, 0, boston->GetMipCount() - 1);
762 auto buffer = context->CreateCommandBuffer();
766 buffer->SetLabel(
"Playground Command Buffer");
769 auto pass = buffer->CreateBlitPass();
773 pass->SetLabel(
"Playground Blit Pass");
775 pass->GenerateMipmap(boston,
"Boston Mipmap");
777 pass->EncodeCommands(context->GetResourceAllocator());
783 auto pass = buffer->CreateRenderPass(render_target);
787 pass->SetLabel(
"Playground Render Pass");
789 pass->SetCommandLabel(
"Image LOD");
790 pass->SetPipeline(mipmaps_pipeline);
791 pass->SetVertexBuffer(vertex_buffer);
793 VS::FrameInfo frame_info;
794 EXPECT_EQ(pass->GetOrthographicTransform(),
796 frame_info.mvp = pass->GetOrthographicTransform() *
798 VS::BindFrameInfo(*pass, host_buffer->EmplaceUniform(frame_info));
800 FS::FragInfo frag_info;
802 FS::BindFragInfo(*pass, host_buffer->EmplaceUniform(frag_info));
805 sampler_desc.
mip_filter = mip_filters[selected_mip_filter];
806 sampler_desc.
min_filter = min_filters[selected_min_filter];
807 const std::unique_ptr<const Sampler>& sampler =
808 context->GetSamplerLibrary()->GetSampler(sampler_desc);
809 FS::BindTex(*pass, boston, sampler);
813 pass->EncodeCommands();
816 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
819 host_buffer->Reset();
822 OpenPlaygroundHere(callback);
826 using VS = ImpellerVertexShader;
827 using FS = ImpellerFragmentShader;
829 auto context = GetContext();
830 auto pipeline_descriptor =
832 ASSERT_TRUE(pipeline_descriptor.has_value());
834 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
836 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
837 ASSERT_TRUE(pipeline && pipeline->IsValid());
839 auto blue_noise = CreateTextureForFixture(
"blue_noise.png");
843 const std::unique_ptr<const Sampler>& noise_sampler =
844 context->GetSamplerLibrary()->GetSampler(noise_sampler_desc);
846 auto cube_map = CreateTextureCubeForFixture(
847 {
"table_mountain_px.png",
"table_mountain_nx.png",
848 "table_mountain_py.png",
"table_mountain_ny.png",
849 "table_mountain_pz.png",
"table_mountain_nz.png"});
850 const std::unique_ptr<const Sampler>& cube_map_sampler =
851 context->GetSamplerLibrary()->GetSampler({});
854 SinglePassCallback callback = [&](
RenderPass& pass) {
855 auto size = pass.GetRenderTargetSize();
857 pass.SetPipeline(pipeline);
858 pass.SetCommandLabel(
"Impeller SDF scene");
861 {
Point(0, size.height)},
862 {
Point(size.width, 0)},
863 {
Point(size.width, 0)},
864 {
Point(0, size.height)},
865 {
Point(size.width, size.height)}});
868 VS::FrameInfo frame_info;
870 frame_info.mvp = pass.GetOrthographicTransform();
871 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
873 FS::FragInfo fs_uniform;
874 fs_uniform.texture_size =
Point(size);
875 fs_uniform.time = GetSecondsElapsed();
876 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(fs_uniform));
877 FS::BindBlueNoise(pass, blue_noise, noise_sampler);
878 FS::BindCubeMap(pass, cube_map, cube_map_sampler);
881 host_buffer->Reset();
884 OpenPlaygroundHere(callback);
888 using VS = ArrayVertexShader;
889 using FS = ArrayFragmentShader;
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());
902 SinglePassCallback callback = [&](
RenderPass& pass) {
903 auto size = pass.GetRenderTargetSize();
905 pass.SetPipeline(pipeline);
906 pass.SetCommandLabel(
"Google Dots");
909 {
Point(0, size.height)},
910 {
Point(size.width, 0)},
911 {
Point(size.width, 0)},
912 {
Point(0, size.height)},
913 {
Point(size.width, size.height)}});
916 VS::FrameInfo frame_info;
920 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
922 auto time = GetSecondsElapsed();
923 auto y_pos = [&time](
float x) {
924 return 400 + 10 * std::cos(time * 5 + x / 6);
927 FS::FragInfo fs_uniform = {
928 .circle_positions = {
Point(430, y_pos(0)),
Point(480, y_pos(1)),
935 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(fs_uniform));
938 host_buffer->Reset();
941 OpenPlaygroundHere(callback);
945 using VS = InactiveUniformsVertexShader;
946 using FS = InactiveUniformsFragmentShader;
948 auto context = GetContext();
949 auto pipeline_descriptor =
951 ASSERT_TRUE(pipeline_descriptor.has_value());
953 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
955 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
956 ASSERT_TRUE(pipeline && pipeline->IsValid());
959 SinglePassCallback callback = [&](
RenderPass& pass) {
960 auto size = pass.GetRenderTargetSize();
962 pass.SetPipeline(pipeline);
963 pass.SetCommandLabel(
"Inactive Uniform");
967 {
Point(0, size.height)},
968 {
Point(size.width, 0)},
969 {
Point(size.width, 0)},
970 {
Point(0, size.height)},
971 {
Point(size.width, size.height)}});
974 VS::FrameInfo frame_info;
978 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
980 FS::FragInfo fs_uniform = {.unused_color =
Color::Red(),
982 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(fs_uniform));
985 host_buffer->Reset();
988 OpenPlaygroundHere(callback);
993 GTEST_SKIP_(
"CPU backed textures are not supported on OpenGLES.");
996 auto context = GetContext();
997 auto allocator = context->GetResourceAllocator();
998 size_t dimension = 2;
1001 ISize size(dimension, dimension);
1005 texture_descriptor.
size = size;
1007 std::max(
static_cast<uint16_t
>(size.
width * 4),
1008 allocator->MinimumBytesPerRow(texture_descriptor.
format));
1009 auto buffer_size = size.
height * row_bytes;
1013 buffer_descriptor.
size = buffer_size;
1015 auto buffer = allocator->CreateBuffer(buffer_descriptor);
1017 ASSERT_TRUE(buffer);
1019 auto texture = buffer->AsTexture(*allocator, texture_descriptor, row_bytes);
1021 ASSERT_TRUE(texture);
1022 ASSERT_TRUE(texture->IsValid());
1025 }
while (dimension <= 8192);
1029 using VS = BoxFadeVertexShader;
1039 using VS = BoxFadeVertexShader;
1048 using VS = BoxFadeVertexShader;
1052 {{100, 100, 0.0}, {0.0, 0.0}},
1053 {{800, 100, 0.0}, {1.0, 0.0}},
1054 {{800, 800, 0.0}, {1.0, 1.0}},
1055 {{100, 800, 0.0}, {0.0, 1.0}},
1071 labels_.push_back(
"Never");
1073 labels_.push_back(
"Always");
1075 labels_.push_back(
"Less");
1077 labels_.push_back(
"Equal");
1079 labels_.push_back(
"LessEqual");
1081 labels_.push_back(
"Greater");
1083 labels_.push_back(
"NotEqual");
1085 labels_.push_back(
"GreaterEqual");
1087 assert(labels_.size() == functions_.size());
1090 const char*
const*
labels()
const {
return &labels_[0]; }
1092 int size()
const {
return labels_.size(); }
1095 for (
size_t i = 0; i < functions_.size(); i++) {
1096 if (functions_[i] == func) {
1107 std::vector<const char*> labels_;
1108 std::vector<CompareFunction> functions_;
1117 using VS = BoxFadeVertexShader;
1118 using FS = BoxFadeFragmentShader;
1119 auto context = GetContext();
1120 ASSERT_TRUE(context);
1122 auto desc = BoxFadePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
1123 ASSERT_TRUE(desc.has_value());
1129 {{100, 100, 0.0}, {0.0, 0.0}},
1130 {{800, 100, 0.0}, {1.0, 0.0}},
1131 {{800, 800, 0.0}, {1.0, 1.0}},
1132 {{100, 100, 0.0}, {0.0, 0.0}},
1133 {{800, 800, 0.0}, {1.0, 1.0}},
1134 {{100, 800, 0.0}, {0.0, 1.0}},
1136 auto vertex_buffer =
1138 ASSERT_TRUE(vertex_buffer);
1141 desc->SetStencilAttachmentDescriptors(std::nullopt);
1143 auto bridge = CreateTextureForFixture(
"bay_bridge.jpg");
1144 auto boston = CreateTextureForFixture(
"boston.jpg");
1145 ASSERT_TRUE(bridge && boston);
1146 const std::unique_ptr<const Sampler>& sampler =
1147 context->GetSamplerLibrary()->GetSampler({});
1148 ASSERT_TRUE(sampler);
1150 static bool mirror =
false;
1151 static int stencil_reference_write = 0xFF;
1152 static int stencil_reference_read = 0x1;
1153 std::vector<uint8_t> stencil_contents;
1154 static int last_stencil_contents_reference_value = 0;
1155 static int current_front_compare =
1157 static int current_back_compare =
1162 auto buffer = context->CreateCommandBuffer();
1166 buffer->SetLabel(
"Playground Command Buffer");
1174 render_target.SetupDepthStencilAttachments(
1175 *context, *context->GetResourceAllocator(),
1176 render_target.GetRenderTargetSize(),
true,
"stencil", stencil_config);
1178 const auto target_width = render_target.GetRenderTargetSize().width;
1179 const auto target_height = render_target.GetRenderTargetSize().height;
1180 const size_t target_size = target_width * target_height;
1181 if (stencil_contents.size() != target_size ||
1182 last_stencil_contents_reference_value != stencil_reference_write) {
1183 stencil_contents.resize(target_size);
1184 last_stencil_contents_reference_value = stencil_reference_write;
1185 for (
int y = 0; y < target_height; y++) {
1186 for (
int x = 0; x < target_width; x++) {
1187 const auto index = y * target_width + x;
1188 const auto kCheckSize = 64;
1190 (((y / kCheckSize) + (x / kCheckSize)) % 2 == 0) *
1191 stencil_reference_write;
1192 stencil_contents[index] = value;
1196 if (!render_target.GetStencilAttachment()->texture->SetContents(
1197 stencil_contents.data(), stencil_contents.size(), 0,
false)) {
1198 VALIDATION_LOG <<
"Could not upload stencil contents to device memory";
1201 auto pass = buffer->CreateRenderPass(render_target);
1205 pass->SetLabel(
"Stencil Buffer");
1206 ImGui::Begin(
"Controls",
nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1207 ImGui::SliderInt(
"Stencil Write Value", &stencil_reference_write, 0,
1209 ImGui::SliderInt(
"Stencil Compare Value", &stencil_reference_read, 0,
1211 ImGui::Checkbox(
"Back face mode", &mirror);
1212 ImGui::ListBox(
"Front face compare function", ¤t_front_compare,
1214 ImGui::ListBox(
"Back face compare function", ¤t_back_compare,
1224 desc->SetStencilAttachmentDescriptors(front, back);
1225 auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get();
1227 assert(pipeline && pipeline->IsValid());
1229 pass->SetCommandLabel(
"Box");
1230 pass->SetPipeline(pipeline);
1231 pass->SetStencilReference(stencil_reference_read);
1232 pass->SetVertexBuffer(vertex_buffer);
1234 VS::UniformBuffer uniforms;
1235 EXPECT_EQ(pass->GetOrthographicTransform(),
1237 uniforms.mvp = pass->GetOrthographicTransform() *
1242 VS::BindUniformBuffer(*pass, host_buffer->EmplaceUniform(uniforms));
1244 FS::FrameInfo frame_info;
1245 frame_info.current_time = GetSecondsElapsed();
1246 frame_info.cursor_position = GetCursorPosition();
1247 frame_info.window_size.x = GetWindowSize().width;
1248 frame_info.window_size.y = GetWindowSize().height;
1250 FS::BindFrameInfo(*pass, host_buffer->EmplaceUniform(frame_info));
1251 FS::BindContents1(*pass, boston, sampler);
1252 FS::BindContents2(*pass, bridge, sampler);
1253 if (!pass->Draw().ok()) {
1256 pass->EncodeCommands();
1259 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
1262 host_buffer->Reset();
1265 OpenPlaygroundHere(callback);
1269 auto context = GetContext();
1270 auto cmd_buffer = context->CreateCommandBuffer();
1271 auto render_target_cache = std::make_shared<RenderTargetAllocator>(
1272 GetContext()->GetResourceAllocator());
1274 auto render_target = render_target_cache->CreateOffscreen(
1275 *context, {100, 100}, 1);
1276 auto render_pass = cmd_buffer->CreateRenderPass(render_target);
1278 EXPECT_EQ(render_pass->GetSampleCount(), render_target.GetSampleCount());
1279 EXPECT_EQ(render_pass->GetRenderTargetPixelFormat(),
1280 render_target.GetRenderTargetPixelFormat());
1281 EXPECT_EQ(render_pass->HasStencilAttachment(),
1282 render_target.GetStencilAttachment().has_value());
1283 EXPECT_EQ(render_pass->GetRenderTargetSize(),
1284 render_target.GetRenderTargetSize());
1285 render_pass->EncodeCommands();
1289 RenderTargetCreateOffscreenMSAASetsDefaultDepthStencilFormat) {
1290 auto context = GetContext();
1291 auto render_target_cache = std::make_shared<RenderTargetAllocator>(
1292 GetContext()->GetResourceAllocator());
1294 RenderTarget render_target = render_target_cache->CreateOffscreenMSAA(
1295 *context, {100, 100}, 1);
1297 ->texture->GetTextureDescriptor()
1299 GetContext()->GetCapabilities()->GetDefaultDepthStencilFormat());
1302 template <
class VertexShader,
class FragmentShader>
1304 const std::shared_ptr<Context>& context) {
1306 auto pipeline_desc =
1307 TexturePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
1308 if (!pipeline_desc.has_value()) {
1312 pipeline_desc->SetStencilAttachmentDescriptors(std::nullopt);
1314 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
1315 if (!pipeline || !pipeline->IsValid()) {
1326 GTEST_SKIP_(
"Not supported on GLES.");
1330 using TextureVS = TextureVertexShader;
1331 using TextureFS = TextureFragmentShader;
1333 using SepiaVS = SepiaVertexShader;
1334 using SepiaFS = SepiaFragmentShader;
1336 auto context = GetContext();
1337 ASSERT_TRUE(context);
1339 if (!context->GetCapabilities()->SupportsFramebufferFetch()) {
1341 "This test uses framebuffer fetch and the backend doesn't support it.");
1346 auto texture_pipeline = CreateDefaultPipeline<TextureVS, TextureFS>(context);
1347 auto sepia_pipeline = CreateDefaultPipeline<SepiaVS, SepiaFS>(context);
1349 ASSERT_TRUE(texture_pipeline);
1350 ASSERT_TRUE(sepia_pipeline);
1355 {{100, 100, 0.0}, {0.0, 0.0}},
1356 {{800, 100, 0.0}, {1.0, 0.0}},
1357 {{800, 800, 0.0}, {1.0, 1.0}},
1358 {{100, 100, 0.0}, {0.0, 0.0}},
1359 {{800, 800, 0.0}, {1.0, 1.0}},
1360 {{100, 800, 0.0}, {0.0, 1.0}},
1373 auto boston = CreateTextureForFixture(
"boston.jpg");
1374 ASSERT_TRUE(boston);
1376 const auto& sampler = context->GetSamplerLibrary()->GetSampler({});
1377 ASSERT_TRUE(sampler);
1379 SinglePassCallback callback = [&](
RenderPass& pass) {
1384 pass.SetPipeline(texture_pipeline);
1386 *context->GetResourceAllocator()));
1387 TextureVS::UniformBuffer uniforms;
1390 TextureVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1391 TextureFS::BindTextureContents(pass, boston, sampler);
1392 if (!pass.Draw().ok()) {
1399 pass.SetPipeline(sepia_pipeline);
1401 *context->GetResourceAllocator()));
1402 SepiaVS::UniformBuffer uniforms;
1405 SepiaVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1406 if (!pass.Draw().ok()) {
1413 OpenPlaygroundHere(callback);
1421 GTEST_SKIP_(
"Not supported on GLES.");
1425 using TextureVS = TextureVertexShader;
1426 using TextureFS = TextureFragmentShader;
1428 using SwizzleVS = SepiaVertexShader;
1429 using SwizzleFS = SwizzleFragmentShader;
1431 using SepiaVS = SepiaVertexShader;
1432 using SepiaFS = SepiaFragmentShader;
1434 auto context = GetContext();
1435 ASSERT_TRUE(context);
1437 if (!context->GetCapabilities()->SupportsFramebufferFetch()) {
1439 "This test uses framebuffer fetch and the backend doesn't support it.");
1444 auto texture_pipeline = CreateDefaultPipeline<TextureVS, TextureFS>(context);
1445 auto swizzle_pipeline = CreateDefaultPipeline<SwizzleVS, SwizzleFS>(context);
1446 auto sepia_pipeline = CreateDefaultPipeline<SepiaVS, SepiaFS>(context);
1448 ASSERT_TRUE(texture_pipeline);
1449 ASSERT_TRUE(swizzle_pipeline);
1450 ASSERT_TRUE(sepia_pipeline);
1455 {{100, 100, 0.0}, {0.0, 0.0}},
1456 {{800, 100, 0.0}, {1.0, 0.0}},
1457 {{800, 800, 0.0}, {1.0, 1.0}},
1458 {{100, 100, 0.0}, {0.0, 0.0}},
1459 {{800, 800, 0.0}, {1.0, 1.0}},
1460 {{100, 800, 0.0}, {0.0, 1.0}},
1473 auto boston = CreateTextureForFixture(
"boston.jpg");
1474 ASSERT_TRUE(boston);
1476 const auto& sampler = context->GetSamplerLibrary()->GetSampler({});
1477 ASSERT_TRUE(sampler);
1479 SinglePassCallback callback = [&](
RenderPass& pass) {
1484 pass.SetPipeline(texture_pipeline);
1486 *context->GetResourceAllocator()));
1487 TextureVS::UniformBuffer uniforms;
1490 TextureVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1491 TextureFS::BindTextureContents(pass, boston, sampler);
1492 if (!pass.Draw().ok()) {
1499 pass.SetPipeline(sepia_pipeline);
1501 *context->GetResourceAllocator()));
1502 SepiaVS::UniformBuffer uniforms;
1505 SepiaVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1506 if (!pass.Draw().ok()) {
1513 pass.SetPipeline(swizzle_pipeline);
1515 *context->GetResourceAllocator()));
1516 SwizzleVS::UniformBuffer uniforms;
1519 SwizzleVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1520 if (!pass.Draw().ok()) {
1527 OpenPlaygroundHere(callback);