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->GetResourceAllocator(), context->GetIdleWaiter(),
83 context->GetCapabilities()->GetMinimumUniformAlignment());
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();
149 context->GetResourceAllocator(), context->GetIdleWaiter(),
150 context->GetCapabilities()->GetMinimumUniformAlignment());
161 *context->GetResourceAllocator());
163 SinglePassCallback callback = [&](
RenderPass& pass) {
164 pass.SetPipeline(pipeline);
165 pass.SetVertexBuffer(vertex_buffer);
167 FS::FragInfo frag_info;
168 frag_info.time = fml::TimePoint::Now().ToEpochDelta().ToSecondsF();
171 context->GetResourceAllocator(), context->GetIdleWaiter(),
172 context->GetCapabilities()->GetMinimumUniformAlignment());
173 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(frag_info));
175 return pass.Draw().ok();
177 OpenPlaygroundHere(callback);
181 using VS = ColorsVertexShader;
182 using FS = ColorsFragmentShader;
183 auto context = GetContext();
184 ASSERT_TRUE(context);
186 ASSERT_TRUE(desc.has_value());
190 desc->ClearStencilAttachments();
194 auto vertex_desc = std::make_shared<VertexDescriptor>();
201 const std::vector<ShaderStageIOSlot> io_slots = {position_slot, color_slot};
202 const std::vector<ShaderStageBufferLayout> layouts = {
205 vertex_desc->RegisterDescriptorSetLayouts(VS::kDescriptorSetLayouts);
206 vertex_desc->RegisterDescriptorSetLayouts(FS::kDescriptorSetLayouts);
207 vertex_desc->SetStageInputs(io_slots, layouts);
208 desc->SetVertexDescriptor(std::move(vertex_desc));
210 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
211 ASSERT_TRUE(pipeline);
230 uint16_t indices[36] = {
240 auto device_buffer = context->GetResourceAllocator()->CreateBufferWithCopy(
241 reinterpret_cast<uint8_t*
>(&cube),
sizeof(cube));
244 ASSERT_TRUE(sampler);
248 context->GetResourceAllocator(), context->GetIdleWaiter(),
249 context->GetCapabilities()->GetMinimumUniformAlignment());
250 SinglePassCallback callback = [&](
RenderPass& pass) {
254 ImGui::Begin(
"Controls",
nullptr, ImGuiWindowFlags_AlwaysAutoResize);
255 ImGui::SliderFloat(
"Field of view", &fov_y.
degrees, 0, 180);
256 ImGui::SliderFloat(
"Camera distance", &
distance, 0, 30);
259 pass.SetCommandLabel(
"Perspective Cube");
260 pass.SetPipeline(pipeline);
262 std::array<BufferView, 2> vertex_buffers = {
264 Range(offsetof(Cube, positions),
sizeof(Cube::positions))),
266 Range(offsetof(Cube, colors),
sizeof(Cube::colors))),
270 device_buffer,
Range(offsetof(Cube, indices),
sizeof(Cube::indices)));
271 pass.SetVertexBuffer(vertex_buffers.data(), vertex_buffers.size());
272 pass.SetElementCount(36);
275 VS::UniformBuffer uniforms;
276 Scalar time = GetSecondsElapsed();
277 euler_angles =
Vector3(0.19 * time, 0.7 * time, 0.43 * time);
285 VS::BindUniformBuffer(pass, host_buffer->EmplaceUniform(uniforms));
287 host_buffer->Reset();
288 return pass.Draw().ok();
290 OpenPlaygroundHere(callback);
294 using VS = BoxFadeVertexShader;
295 using FS = BoxFadeFragmentShader;
296 auto context = GetContext();
297 ASSERT_TRUE(context);
299 auto desc = BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
300 ASSERT_TRUE(desc.has_value());
302 desc->SetStencilAttachmentDescriptors(std::nullopt);
304 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
305 ASSERT_TRUE(box_pipeline);
311 {{100, 100, 0.0}, {0.0, 0.0}},
312 {{800, 100, 0.0}, {1.0, 0.0}},
313 {{800, 800, 0.0}, {1.0, 1.0}},
314 {{100, 100, 0.0}, {0.0, 0.0}},
315 {{800, 800, 0.0}, {1.0, 1.0}},
316 {{100, 800, 0.0}, {0.0, 1.0}},
320 ASSERT_TRUE(vertex_buffer);
322 auto bridge = CreateTextureForFixture(
"bay_bridge.jpg");
323 auto boston = CreateTextureForFixture(
"boston.jpg");
324 ASSERT_TRUE(bridge && boston);
326 ASSERT_TRUE(sampler);
329 context->GetResourceAllocator(), context->GetIdleWaiter(),
330 context->GetCapabilities()->GetMinimumUniformAlignment());
331 SinglePassCallback callback = [&](
RenderPass& pass) {
332 for (
size_t i = 0; i < 1; i++) {
333 for (
size_t j = 0; j < 1; j++) {
334 pass.SetCommandLabel(
"Box");
335 pass.SetPipeline(box_pipeline);
336 pass.SetVertexBuffer(vertex_buffer);
338 FS::FrameInfo frame_info;
339 frame_info.current_time = GetSecondsElapsed();
340 frame_info.cursor_position = GetCursorPosition();
341 frame_info.window_size.x = GetWindowSize().width;
342 frame_info.window_size.y = GetWindowSize().height;
344 FS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
345 FS::BindContents1(pass, boston, sampler);
346 FS::BindContents2(pass, bridge, sampler);
348 VS::UniformBuffer uniforms;
349 EXPECT_EQ(pass.GetOrthographicTransform(),
351 uniforms.mvp = pass.GetOrthographicTransform() *
354 VS::BindUniformBuffer(pass, host_buffer->EmplaceUniform(uniforms));
355 if (!pass.Draw().ok()) {
361 host_buffer->Reset();
364 OpenPlaygroundHere(callback);
368 using VS = BoxFadeVertexShader;
369 using FS = BoxFadeFragmentShader;
370 auto context = GetContext();
371 ASSERT_TRUE(context);
374 BoxPipelineBuilder::MakeDefaultPipelineDescriptor(*context);
376 pipeline_desc->ClearDepthAttachment();
379 ASSERT_TRUE(pipeline_desc.has_value());
381 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
382 ASSERT_TRUE(box_pipeline);
384 context->GetResourceAllocator(), context->GetIdleWaiter(),
385 context->GetCapabilities()->GetMinimumUniformAlignment());
390 {{100, 100, 0.0}, {0.0, 0.0}},
391 {{800, 100, 0.0}, {1.0, 0.0}},
392 {{800, 800, 0.0}, {1.0, 1.0}},
393 {{100, 100, 0.0}, {0.0, 0.0}},
394 {{800, 800, 0.0}, {1.0, 1.0}},
395 {{100, 800, 0.0}, {0.0, 1.0}},
399 ASSERT_TRUE(vertex_buffer);
401 auto bridge = CreateTextureForFixture(
"bay_bridge.jpg");
402 auto boston = CreateTextureForFixture(
"boston.jpg");
403 ASSERT_TRUE(bridge && boston);
405 ASSERT_TRUE(sampler);
407 std::shared_ptr<RenderPass> r2t_pass;
408 auto cmd_buffer = context->CreateCommandBuffer();
409 ASSERT_TRUE(cmd_buffer);
416 ASSERT_NE(pipeline_desc->GetColorAttachmentDescriptor(0u),
nullptr);
417 texture_descriptor.
format =
418 pipeline_desc->GetColorAttachmentDescriptor(0u)->format;
420 texture_descriptor.
size = {400, 400};
425 context->GetResourceAllocator()->CreateTexture(texture_descriptor);
429 color0.
texture->SetLabel(
"r2t_target");
436 stencil_texture_desc.
size = texture_descriptor.
size;
440 context->GetResourceAllocator()->CreateTexture(stencil_texture_desc);
445 r2t_pass = cmd_buffer->CreateRenderPass(r2t_desc);
446 ASSERT_TRUE(r2t_pass && r2t_pass->IsValid());
449 r2t_pass->SetCommandLabel(
"Box");
450 r2t_pass->SetPipeline(box_pipeline);
451 r2t_pass->SetVertexBuffer(vertex_buffer);
453 FS::FrameInfo frame_info;
454 frame_info.current_time = GetSecondsElapsed();
455 frame_info.cursor_position = GetCursorPosition();
456 frame_info.window_size.x = GetWindowSize().width;
457 frame_info.window_size.y = GetWindowSize().height;
459 FS::BindFrameInfo(*r2t_pass, host_buffer->EmplaceUniform(frame_info));
460 FS::BindContents1(*r2t_pass, boston, sampler);
461 FS::BindContents2(*r2t_pass, bridge, sampler);
463 VS::UniformBuffer uniforms;
466 VS::BindUniformBuffer(*r2t_pass, host_buffer->EmplaceUniform(uniforms));
467 ASSERT_TRUE(r2t_pass->Draw().ok());
468 ASSERT_TRUE(r2t_pass->EncodeCommands());
473 GTEST_SKIP() <<
"Instancing is not supported on OpenGL.";
475 using VS = InstancedDrawVertexShader;
476 using FS = InstancedDrawFragmentShader;
480 VS::PerVertexData{
Point{10, 10}},
481 VS::PerVertexData{
Point{10, 110}},
482 VS::PerVertexData{
Point{110, 10}},
483 VS::PerVertexData{
Point{10, 110}},
484 VS::PerVertexData{
Point{110, 10}},
485 VS::PerVertexData{
Point{110, 110}},
488 ASSERT_NE(GetContext(),
nullptr);
491 ->GetPipelineLibrary()
495 .SetStencilAttachmentDescriptors(std::nullopt))
498 ASSERT_TRUE(pipeline && pipeline->IsValid());
500 static constexpr
size_t kInstancesCount = 5u;
501 VS::InstanceInfo<kInstancesCount> instances;
502 for (
size_t i = 0; i < kInstancesCount; i++) {
507 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
508 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
509 ASSERT_TRUE(OpenPlaygroundHere([&](
RenderPass& pass) ->
bool {
513 VS::FrameInfo frame_info;
518 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
519 VS::BindInstanceInfo(pass, host_buffer->EmplaceStorageBuffer(instances));
525 host_buffer->Reset();
532 GTEST_SKIP() <<
"Mipmap test shader not supported on GLES.";
534 auto context = GetContext();
535 ASSERT_TRUE(context);
537 using VS = MipmapsVertexShader;
538 using FS = MipmapsFragmentShader;
540 ASSERT_TRUE(desc.has_value());
542 desc->SetStencilAttachmentDescriptors(std::nullopt);
543 auto mipmaps_pipeline =
544 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
545 ASSERT_TRUE(mipmaps_pipeline);
550 texture_desc.
size = {800, 600};
553 auto texture = context->GetResourceAllocator()->CreateTexture(texture_desc);
554 ASSERT_TRUE(texture);
556 auto bridge = CreateTextureForFixture(
"bay_bridge.jpg");
557 auto boston = CreateTextureForFixture(
"boston.jpg");
558 ASSERT_TRUE(bridge && boston);
560 ASSERT_TRUE(sampler);
565 auto size =
Point(boston->GetSize());
567 {{0, 0}, {0.0, 0.0}},
568 {{size.x, 0}, {1.0, 0.0}},
569 {{size.x, size.y}, {1.0, 1.0}},
570 {{0, 0}, {0.0, 0.0}},
571 {{size.x, size.y}, {1.0, 1.0}},
572 {{0, size.y}, {0.0, 1.0}},
576 ASSERT_TRUE(vertex_buffer);
579 context->GetResourceAllocator(), context->GetIdleWaiter(),
580 context->GetCapabilities()->GetMinimumUniformAlignment());
582 auto buffer = context->CreateCommandBuffer();
586 buffer->SetLabel(
"Playground Command Buffer");
589 auto pass = buffer->CreateBlitPass();
593 pass->SetLabel(
"Playground Blit Pass");
596 pass->AddCopy(bridge, texture);
598 if (!pass->EncodeCommands()) {
604 auto pass = buffer->CreateRenderPass(render_target);
608 pass->SetLabel(
"Playground Render Pass");
610 pass->SetCommandLabel(
"Image");
611 pass->SetPipeline(mipmaps_pipeline);
612 pass->SetVertexBuffer(vertex_buffer);
614 VS::FrameInfo frame_info;
615 EXPECT_EQ(pass->GetOrthographicTransform(),
617 frame_info.mvp = pass->GetOrthographicTransform() *
619 VS::BindFrameInfo(*pass, host_buffer->EmplaceUniform(frame_info));
621 FS::FragInfo frag_info;
623 FS::BindFragInfo(*pass, host_buffer->EmplaceUniform(frag_info));
625 auto sampler = context->GetSamplerLibrary()->GetSampler({});
626 FS::BindTex(*pass, texture, sampler);
630 pass->EncodeCommands();
633 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
636 host_buffer->Reset();
639 OpenPlaygroundHere(callback);
644 GTEST_SKIP() <<
"Mipmap test shader not supported on GLES.";
646 auto context = GetContext();
647 ASSERT_TRUE(context);
649 using VS = MipmapsVertexShader;
650 using FS = MipmapsFragmentShader;
652 ASSERT_TRUE(desc.has_value());
654 desc->SetStencilAttachmentDescriptors(std::nullopt);
655 auto mipmaps_pipeline =
656 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
657 ASSERT_TRUE(mipmaps_pipeline);
659 auto bridge = CreateTextureForFixture(
"bay_bridge.jpg");
660 auto boston = CreateTextureForFixture(
"boston.jpg");
661 ASSERT_TRUE(bridge && boston);
663 ASSERT_TRUE(sampler);
668 texture_desc.
size = bridge->GetTextureDescriptor().size;
674 device_buffer_desc.
size =
675 bridge->GetTextureDescriptor().GetByteSizeOfBaseMipLevel();
677 context->GetResourceAllocator()->CreateBuffer(device_buffer_desc);
682 auto size =
Point(boston->GetSize());
684 {{0, 0}, {0.0, 0.0}},
685 {{size.x, 0}, {1.0, 0.0}},
686 {{size.x, size.y}, {1.0, 1.0}},
687 {{0, 0}, {0.0, 0.0}},
688 {{size.x, size.y}, {1.0, 1.0}},
689 {{0, size.y}, {0.0, 1.0}},
693 ASSERT_TRUE(vertex_buffer);
696 context->GetResourceAllocator(), context->GetIdleWaiter(),
697 context->GetCapabilities()->GetMinimumUniformAlignment());
700 auto buffer = context->CreateCommandBuffer();
704 buffer->SetLabel(
"Playground Command Buffer");
705 auto pass = buffer->CreateBlitPass();
709 pass->SetLabel(
"Playground Blit Pass");
712 pass->AddCopy(bridge, device_buffer);
713 pass->EncodeCommands();
715 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
721 auto buffer = context->CreateCommandBuffer();
725 buffer->SetLabel(
"Playground Command Buffer");
727 auto pass = buffer->CreateRenderPass(render_target);
731 pass->SetLabel(
"Playground Render Pass");
733 pass->SetCommandLabel(
"Image");
734 pass->SetPipeline(mipmaps_pipeline);
735 pass->SetVertexBuffer(vertex_buffer);
737 VS::FrameInfo frame_info;
738 EXPECT_EQ(pass->GetOrthographicTransform(),
740 frame_info.mvp = pass->GetOrthographicTransform() *
742 VS::BindFrameInfo(*pass, host_buffer->EmplaceUniform(frame_info));
744 FS::FragInfo frag_info;
746 FS::BindFragInfo(*pass, host_buffer->EmplaceUniform(frag_info));
749 context->GetSamplerLibrary()->GetSampler({});
752 context->GetResourceAllocator()->CreateTexture(texture_desc);
753 if (!texture->SetContents(device_buffer->OnGetContents(),
758 FS::BindTex(*pass, texture, sampler);
762 pass->EncodeCommands();
763 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
767 host_buffer->Reset();
770 OpenPlaygroundHere(callback);
775 GTEST_SKIP() <<
"Mipmap test shader not supported on GLES.";
777 auto context = GetContext();
778 ASSERT_TRUE(context);
780 using VS = MipmapsVertexShader;
781 using FS = MipmapsFragmentShader;
783 ASSERT_TRUE(desc.has_value());
785 desc->SetStencilAttachmentDescriptors(std::nullopt);
786 auto mipmaps_pipeline =
787 context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get();
788 ASSERT_TRUE(mipmaps_pipeline);
790 auto boston = CreateTextureForFixture(
"boston.jpg",
true);
796 auto size =
Point(boston->GetSize());
798 {{0, 0}, {0.0, 0.0}},
799 {{size.x, 0}, {1.0, 0.0}},
800 {{size.x, size.y}, {1.0, 1.0}},
801 {{0, 0}, {0.0, 0.0}},
802 {{size.x, size.y}, {1.0, 1.0}},
803 {{0, size.y}, {0.0, 1.0}},
807 ASSERT_TRUE(vertex_buffer);
809 bool first_frame =
true;
811 context->GetResourceAllocator(), context->GetIdleWaiter(),
812 context->GetCapabilities()->GetMinimumUniformAlignment());
814 const char* mip_filter_names[] = {
"Base",
"Nearest",
"Linear"};
817 const char* min_filter_names[] = {
"Nearest",
"Linear"};
822 static int selected_mip_filter = 1;
823 static int selected_min_filter = 0;
824 static float lod = 4.5;
826 ImGui::Begin(
"Controls",
nullptr, ImGuiWindowFlags_AlwaysAutoResize);
827 ImGui::Combo(
"Mip filter", &selected_mip_filter, mip_filter_names,
828 sizeof(mip_filter_names) /
sizeof(
char*));
829 ImGui::Combo(
"Min filter", &selected_min_filter, min_filter_names,
830 sizeof(min_filter_names) /
sizeof(
char*));
831 ImGui::SliderFloat(
"LOD", &lod, 0, boston->GetMipCount() - 1);
834 auto buffer = context->CreateCommandBuffer();
838 buffer->SetLabel(
"Playground Command Buffer");
841 auto pass = buffer->CreateBlitPass();
845 pass->SetLabel(
"Playground Blit Pass");
847 pass->GenerateMipmap(boston,
"Boston Mipmap");
849 pass->EncodeCommands();
855 auto pass = buffer->CreateRenderPass(render_target);
859 pass->SetLabel(
"Playground Render Pass");
861 pass->SetCommandLabel(
"Image LOD");
862 pass->SetPipeline(mipmaps_pipeline);
863 pass->SetVertexBuffer(vertex_buffer);
865 VS::FrameInfo frame_info;
866 EXPECT_EQ(pass->GetOrthographicTransform(),
868 frame_info.mvp = pass->GetOrthographicTransform() *
870 VS::BindFrameInfo(*pass, host_buffer->EmplaceUniform(frame_info));
872 FS::FragInfo frag_info;
874 FS::BindFragInfo(*pass, host_buffer->EmplaceUniform(frag_info));
877 sampler_desc.
mip_filter = mip_filters[selected_mip_filter];
878 sampler_desc.
min_filter = min_filters[selected_min_filter];
880 context->GetSamplerLibrary()->GetSampler(sampler_desc);
881 FS::BindTex(*pass, boston, sampler);
885 pass->EncodeCommands();
888 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
891 host_buffer->Reset();
894 OpenPlaygroundHere(callback);
898 using VS = ImpellerVertexShader;
899 using FS = ImpellerFragmentShader;
901 auto context = GetContext();
902 auto pipeline_descriptor =
904 ASSERT_TRUE(pipeline_descriptor.has_value());
906 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
908 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
909 ASSERT_TRUE(pipeline && pipeline->IsValid());
911 auto blue_noise = CreateTextureForFixture(
"blue_noise.png");
916 context->GetSamplerLibrary()->GetSampler(noise_sampler_desc);
918 auto cube_map = CreateTextureCubeForFixture(
919 {
"table_mountain_px.png",
"table_mountain_nx.png",
920 "table_mountain_py.png",
"table_mountain_ny.png",
921 "table_mountain_pz.png",
"table_mountain_nz.png"});
923 context->GetSamplerLibrary()->GetSampler({});
925 context->GetResourceAllocator(), context->GetIdleWaiter(),
926 context->GetCapabilities()->GetMinimumUniformAlignment());
928 SinglePassCallback callback = [&](
RenderPass& pass) {
929 auto size = pass.GetRenderTargetSize();
931 pass.SetPipeline(pipeline);
932 pass.SetCommandLabel(
"Impeller SDF scene");
935 {
Point(0, size.height)},
936 {
Point(size.width, 0)},
937 {
Point(size.width, 0)},
938 {
Point(0, size.height)},
939 {
Point(size.width, size.height)}});
942 VS::FrameInfo frame_info;
944 frame_info.mvp = pass.GetOrthographicTransform();
945 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
947 FS::FragInfo fs_uniform;
948 fs_uniform.texture_size =
Point(size);
949 fs_uniform.time = GetSecondsElapsed();
950 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(fs_uniform));
951 FS::BindBlueNoise(pass, blue_noise, noise_sampler);
952 FS::BindCubeMap(pass, cube_map, cube_map_sampler);
955 host_buffer->Reset();
958 OpenPlaygroundHere(callback);
962 using VS = PlanetVertexShader;
963 using FS = PlanetFragmentShader;
965 auto context = GetContext();
966 auto pipeline_descriptor =
968 ASSERT_TRUE(pipeline_descriptor.has_value());
970 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
972 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
973 ASSERT_TRUE(pipeline && pipeline->IsValid());
976 context->GetResourceAllocator(), context->GetIdleWaiter(),
977 context->GetCapabilities()->GetMinimumUniformAlignment());
979 SinglePassCallback callback = [&](
RenderPass& pass) {
980 static Scalar speed = 0.1;
981 static Scalar planet_size = 550.0;
982 static bool show_normals =
false;
983 static bool show_noise =
false;
984 static Scalar seed_value = 42.0;
986 auto size = pass.GetRenderTargetSize();
988 ImGui::Begin(
"Controls",
nullptr, ImGuiWindowFlags_AlwaysAutoResize);
989 ImGui::SliderFloat(
"Speed", &speed, 0.0, 10.0);
990 ImGui::SliderFloat(
"Planet Size", &planet_size, 0.1, 1000);
991 ImGui::Checkbox(
"Show Normals", &show_normals);
992 ImGui::Checkbox(
"Show Noise", &show_noise);
993 ImGui::InputFloat(
"Seed Value", &seed_value);
996 pass.SetPipeline(pipeline);
997 pass.SetCommandLabel(
"Planet scene");
1000 {
Point(0, size.height)},
1001 {
Point(size.width, 0)},
1002 {
Point(size.width, 0)},
1003 {
Point(0, size.height)},
1004 {
Point(size.width, size.height)}});
1007 VS::FrameInfo frame_info;
1009 frame_info.mvp = pass.GetOrthographicTransform();
1010 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
1012 FS::FragInfo fs_uniform;
1013 fs_uniform.resolution =
Point(size);
1014 fs_uniform.time = GetSecondsElapsed();
1015 fs_uniform.speed = speed;
1016 fs_uniform.planet_size = planet_size;
1017 fs_uniform.show_normals = show_normals ? 1.0 : 0.0;
1018 fs_uniform.show_noise = show_noise ? 1.0 : 0.0;
1019 fs_uniform.seed_value = seed_value;
1020 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(fs_uniform));
1023 host_buffer->Reset();
1026 OpenPlaygroundHere(callback);
1030 using VS = ArrayVertexShader;
1031 using FS = ArrayFragmentShader;
1033 auto context = GetContext();
1034 auto pipeline_descriptor =
1036 ASSERT_TRUE(pipeline_descriptor.has_value());
1038 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
1040 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
1041 ASSERT_TRUE(pipeline && pipeline->IsValid());
1044 context->GetResourceAllocator(), context->GetIdleWaiter(),
1045 context->GetCapabilities()->GetMinimumUniformAlignment());
1046 SinglePassCallback callback = [&](
RenderPass& pass) {
1047 auto size = pass.GetRenderTargetSize();
1049 pass.SetPipeline(pipeline);
1050 pass.SetCommandLabel(
"Google Dots");
1053 {
Point(0, size.height)},
1054 {
Point(size.width, 0)},
1055 {
Point(size.width, 0)},
1056 {
Point(0, size.height)},
1057 {
Point(size.width, size.height)}});
1060 VS::FrameInfo frame_info;
1064 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
1066 auto time = GetSecondsElapsed();
1067 auto y_pos = [&time](
float x) {
1068 return 400 + 10 * std::cos(time * 5 +
x / 6);
1071 FS::FragInfo fs_uniform = {
1072 .circle_positions = {
Point(430, y_pos(0)),
Point(480, y_pos(1)),
1079 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(fs_uniform));
1082 host_buffer->Reset();
1085 OpenPlaygroundHere(callback);
1089 using VS = InactiveUniformsVertexShader;
1090 using FS = InactiveUniformsFragmentShader;
1092 auto context = GetContext();
1093 auto pipeline_descriptor =
1095 ASSERT_TRUE(pipeline_descriptor.has_value());
1097 pipeline_descriptor->SetStencilAttachmentDescriptors(std::nullopt);
1099 context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
1100 ASSERT_TRUE(pipeline && pipeline->IsValid());
1103 context->GetResourceAllocator(), context->GetIdleWaiter(),
1104 context->GetCapabilities()->GetMinimumUniformAlignment());
1105 SinglePassCallback callback = [&](
RenderPass& pass) {
1106 auto size = pass.GetRenderTargetSize();
1108 pass.SetPipeline(pipeline);
1109 pass.SetCommandLabel(
"Inactive Uniform");
1113 {
Point(0, size.height)},
1114 {
Point(size.width, 0)},
1115 {
Point(size.width, 0)},
1116 {
Point(0, size.height)},
1117 {
Point(size.width, size.height)}});
1120 VS::FrameInfo frame_info;
1124 VS::BindFrameInfo(pass, host_buffer->EmplaceUniform(frame_info));
1126 FS::FragInfo fs_uniform = {.unused_color =
Color::Red(),
1128 FS::BindFragInfo(pass, host_buffer->EmplaceUniform(fs_uniform));
1131 host_buffer->Reset();
1134 OpenPlaygroundHere(callback);
1138 using VS = BoxFadeVertexShader;
1148 using VS = BoxFadeVertexShader;
1157 using VS = BoxFadeVertexShader;
1161 {{100, 100, 0.0}, {0.0, 0.0}},
1162 {{800, 100, 0.0}, {1.0, 0.0}},
1163 {{800, 800, 0.0}, {1.0, 1.0}},
1164 {{100, 800, 0.0}, {0.0, 1.0}},
1180 labels_.push_back(
"Never");
1182 labels_.push_back(
"Always");
1184 labels_.push_back(
"Less");
1186 labels_.push_back(
"Equal");
1188 labels_.push_back(
"LessEqual");
1190 labels_.push_back(
"Greater");
1192 labels_.push_back(
"NotEqual");
1194 labels_.push_back(
"GreaterEqual");
1196 assert(labels_.size() == functions_.size());
1199 const char*
const*
labels()
const {
return &labels_[0]; }
1201 int size()
const {
return labels_.size(); }
1204 for (
size_t i = 0; i < functions_.size(); i++) {
1205 if (functions_[i] == func) {
1216 std::vector<const char*> labels_;
1217 std::vector<CompareFunction> functions_;
1226 using VS = BoxFadeVertexShader;
1227 using FS = BoxFadeFragmentShader;
1228 auto context = GetContext();
1229 ASSERT_TRUE(context);
1231 auto desc = BoxFadePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
1232 ASSERT_TRUE(desc.has_value());
1238 {{100, 100, 0.0}, {0.0, 0.0}},
1239 {{800, 100, 0.0}, {1.0, 0.0}},
1240 {{800, 800, 0.0}, {1.0, 1.0}},
1241 {{100, 100, 0.0}, {0.0, 0.0}},
1242 {{800, 800, 0.0}, {1.0, 1.0}},
1243 {{100, 800, 0.0}, {0.0, 1.0}},
1245 auto vertex_buffer =
1247 ASSERT_TRUE(vertex_buffer);
1250 desc->SetStencilAttachmentDescriptors(std::nullopt);
1252 auto bridge = CreateTextureForFixture(
"bay_bridge.jpg");
1253 auto boston = CreateTextureForFixture(
"boston.jpg");
1254 ASSERT_TRUE(bridge && boston);
1256 ASSERT_TRUE(sampler);
1258 static bool mirror =
false;
1259 static int stencil_reference_write = 0xFF;
1260 static int stencil_reference_read = 0x1;
1261 std::vector<uint8_t> stencil_contents;
1262 static int last_stencil_contents_reference_value = 0;
1263 static int current_front_compare =
1265 static int current_back_compare =
1269 context->GetResourceAllocator(), context->GetIdleWaiter(),
1270 context->GetCapabilities()->GetMinimumUniformAlignment());
1272 auto buffer = context->CreateCommandBuffer();
1276 buffer->SetLabel(
"Playground Command Buffer");
1284 render_target.SetupDepthStencilAttachments(
1285 *context, *context->GetResourceAllocator(),
1286 render_target.GetRenderTargetSize(),
true,
"stencil", stencil_config);
1288 const auto target_width = render_target.GetRenderTargetSize().width;
1289 const auto target_height = render_target.GetRenderTargetSize().height;
1290 const size_t target_size = target_width * target_height;
1291 if (stencil_contents.size() != target_size ||
1292 last_stencil_contents_reference_value != stencil_reference_write) {
1293 stencil_contents.resize(target_size);
1294 last_stencil_contents_reference_value = stencil_reference_write;
1295 for (
int y = 0; y < target_height; y++) {
1296 for (
int x = 0;
x < target_width;
x++) {
1297 const auto index = y * target_width +
x;
1298 const auto kCheckSize = 64;
1300 (((y / kCheckSize) + (
x / kCheckSize)) % 2 == 0) *
1301 stencil_reference_write;
1302 stencil_contents[index] =
value;
1306 if (!render_target.GetStencilAttachment()->texture->SetContents(
1307 stencil_contents.data(), stencil_contents.size(), 0,
false)) {
1308 VALIDATION_LOG <<
"Could not upload stencil contents to device memory";
1311 auto pass = buffer->CreateRenderPass(render_target);
1315 pass->SetLabel(
"Stencil Buffer");
1316 ImGui::Begin(
"Controls",
nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1317 ImGui::SliderInt(
"Stencil Write Value", &stencil_reference_write, 0,
1319 ImGui::SliderInt(
"Stencil Compare Value", &stencil_reference_read, 0,
1321 ImGui::Checkbox(
"Back face mode", &mirror);
1322 ImGui::ListBox(
"Front face compare function", ¤t_front_compare,
1324 ImGui::ListBox(
"Back face compare function", ¤t_back_compare,
1334 desc->SetStencilAttachmentDescriptors(front, back);
1335 auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get();
1337 assert(pipeline && pipeline->IsValid());
1339 pass->SetCommandLabel(
"Box");
1340 pass->SetPipeline(pipeline);
1341 pass->SetStencilReference(stencil_reference_read);
1342 pass->SetVertexBuffer(vertex_buffer);
1344 VS::UniformBuffer uniforms;
1345 EXPECT_EQ(pass->GetOrthographicTransform(),
1347 uniforms.mvp = pass->GetOrthographicTransform() *
1352 VS::BindUniformBuffer(*pass, host_buffer->EmplaceUniform(uniforms));
1354 FS::FrameInfo frame_info;
1355 frame_info.current_time = GetSecondsElapsed();
1356 frame_info.cursor_position = GetCursorPosition();
1357 frame_info.window_size.x = GetWindowSize().width;
1358 frame_info.window_size.y = GetWindowSize().height;
1360 FS::BindFrameInfo(*pass, host_buffer->EmplaceUniform(frame_info));
1361 FS::BindContents1(*pass, boston, sampler);
1362 FS::BindContents2(*pass, bridge, sampler);
1363 if (!pass->Draw().ok()) {
1366 pass->EncodeCommands();
1369 if (!context->GetCommandQueue()->Submit({buffer}).ok()) {
1372 host_buffer->Reset();
1375 OpenPlaygroundHere(callback);
1379 auto context = GetContext();
1380 auto cmd_buffer = context->CreateCommandBuffer();
1381 auto render_target_cache = std::make_shared<RenderTargetAllocator>(
1382 GetContext()->GetResourceAllocator());
1384 auto render_target = render_target_cache->CreateOffscreen(
1385 *context, {100, 100}, 1);
1386 auto render_pass = cmd_buffer->CreateRenderPass(render_target);
1388 EXPECT_EQ(render_pass->GetSampleCount(), render_target.GetSampleCount());
1389 EXPECT_EQ(render_pass->GetRenderTargetPixelFormat(),
1390 render_target.GetRenderTargetPixelFormat());
1391 EXPECT_EQ(render_pass->HasStencilAttachment(),
1392 render_target.GetStencilAttachment().has_value());
1393 EXPECT_EQ(render_pass->GetRenderTargetSize(),
1394 render_target.GetRenderTargetSize());
1395 render_pass->EncodeCommands();
1399 RenderTargetCreateOffscreenMSAASetsDefaultDepthStencilFormat) {
1400 auto context = GetContext();
1401 auto render_target_cache = std::make_shared<RenderTargetAllocator>(
1402 GetContext()->GetResourceAllocator());
1404 RenderTarget render_target = render_target_cache->CreateOffscreenMSAA(
1405 *context, {100, 100}, 1);
1407 ->texture->GetTextureDescriptor()
1409 GetContext()->GetCapabilities()->GetDefaultDepthStencilFormat());
1412 template <
class VertexShader,
class FragmentShader>
1414 const std::shared_ptr<Context>& context) {
1416 auto pipeline_desc =
1417 TexturePipelineBuilder::MakeDefaultPipelineDescriptor(*context);
1418 if (!pipeline_desc.has_value()) {
1422 pipeline_desc->SetStencilAttachmentDescriptors(std::nullopt);
1424 context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
1425 if (!pipeline || !pipeline->IsValid()) {
1433 using TextureVS = TextureVertexShader;
1434 using TextureFS = TextureFragmentShader;
1436 using SepiaVS = SepiaVertexShader;
1437 using SepiaFS = SepiaFragmentShader;
1439 auto context = GetContext();
1440 ASSERT_TRUE(context);
1442 if (!context->GetCapabilities()->SupportsFramebufferFetch()) {
1443 GTEST_SKIP() <<
"This test uses framebuffer fetch and the backend doesn't "
1449 auto texture_pipeline = CreateDefaultPipeline<TextureVS, TextureFS>(context);
1450 auto sepia_pipeline = CreateDefaultPipeline<SepiaVS, SepiaFS>(context);
1452 ASSERT_TRUE(texture_pipeline);
1453 ASSERT_TRUE(sepia_pipeline);
1458 {{100, 100, 0.0}, {0.0, 0.0}},
1459 {{800, 100, 0.0}, {1.0, 0.0}},
1460 {{800, 800, 0.0}, {1.0, 1.0}},
1461 {{100, 100, 0.0}, {0.0, 0.0}},
1462 {{800, 800, 0.0}, {1.0, 1.0}},
1463 {{100, 800, 0.0}, {0.0, 1.0}},
1476 auto boston = CreateTextureForFixture(
"boston.jpg");
1477 ASSERT_TRUE(boston);
1479 const auto& sampler = context->GetSamplerLibrary()->GetSampler({});
1480 ASSERT_TRUE(sampler);
1482 SinglePassCallback callback = [&](
RenderPass& pass) {
1484 context->GetResourceAllocator(), context->GetIdleWaiter(),
1485 context->GetCapabilities()->GetMinimumUniformAlignment());
1489 pass.SetPipeline(texture_pipeline);
1491 *context->GetResourceAllocator()));
1492 TextureVS::UniformBuffer uniforms;
1495 TextureVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1496 TextureFS::BindTextureContents(pass, boston, sampler);
1497 if (!pass.Draw().ok()) {
1504 pass.SetPipeline(sepia_pipeline);
1506 *context->GetResourceAllocator()));
1507 SepiaVS::UniformBuffer uniforms;
1510 SepiaVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1511 if (!pass.Draw().ok()) {
1518 OpenPlaygroundHere(callback);
1523 using TextureVS = TextureVertexShader;
1524 using TextureFS = TextureFragmentShader;
1526 using SwizzleVS = SepiaVertexShader;
1527 using SwizzleFS = SwizzleFragmentShader;
1529 using SepiaVS = SepiaVertexShader;
1530 using SepiaFS = SepiaFragmentShader;
1532 auto context = GetContext();
1533 ASSERT_TRUE(context);
1535 if (!context->GetCapabilities()->SupportsFramebufferFetch()) {
1536 GTEST_SKIP() <<
"This test uses framebuffer fetch and the backend doesn't "
1542 auto texture_pipeline = CreateDefaultPipeline<TextureVS, TextureFS>(context);
1543 auto swizzle_pipeline = CreateDefaultPipeline<SwizzleVS, SwizzleFS>(context);
1544 auto sepia_pipeline = CreateDefaultPipeline<SepiaVS, SepiaFS>(context);
1546 ASSERT_TRUE(texture_pipeline);
1547 ASSERT_TRUE(swizzle_pipeline);
1548 ASSERT_TRUE(sepia_pipeline);
1553 {{100, 100, 0.0}, {0.0, 0.0}},
1554 {{800, 100, 0.0}, {1.0, 0.0}},
1555 {{800, 800, 0.0}, {1.0, 1.0}},
1556 {{100, 100, 0.0}, {0.0, 0.0}},
1557 {{800, 800, 0.0}, {1.0, 1.0}},
1558 {{100, 800, 0.0}, {0.0, 1.0}},
1571 auto boston = CreateTextureForFixture(
"boston.jpg");
1572 ASSERT_TRUE(boston);
1574 const auto& sampler = context->GetSamplerLibrary()->GetSampler({});
1575 ASSERT_TRUE(sampler);
1577 SinglePassCallback callback = [&](
RenderPass& pass) {
1579 context->GetResourceAllocator(), context->GetIdleWaiter(),
1580 context->GetCapabilities()->GetMinimumUniformAlignment());
1584 pass.SetPipeline(texture_pipeline);
1586 *context->GetResourceAllocator()));
1587 TextureVS::UniformBuffer uniforms;
1590 TextureVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1591 TextureFS::BindTextureContents(pass, boston, sampler);
1592 if (!pass.Draw().ok()) {
1599 pass.SetPipeline(sepia_pipeline);
1601 *context->GetResourceAllocator()));
1602 SepiaVS::UniformBuffer uniforms;
1605 SepiaVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1606 if (!pass.Draw().ok()) {
1613 pass.SetPipeline(swizzle_pipeline);
1615 *context->GetResourceAllocator()));
1616 SwizzleVS::UniformBuffer uniforms;
1619 SwizzleVS::BindUniformBuffer(pass, buffer->EmplaceUniform(uniforms));
1620 if (!pass.Draw().ok()) {
1627 OpenPlaygroundHere(callback);
1631 using FS = BoxFadeFragmentShader;
1633 auto context = GetContext();
1635 auto command_buffer = context->CreateCommandBuffer();
1640 auto pass = command_buffer->CreateRenderPass(target);
1641 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, size_t minimum_uniform_alignment)
std::function< bool(RenderTarget &render_target)> RenderCallback
Render passes encode render commands directed as one specific render target into an underlying comman...
virtual bool SetVertexBuffer(VertexBuffer buffer)
Specify the vertex and index buffer to use for this command.
const Matrix & GetOrthographicTransform() const
virtual void SetPipeline(PipelineRef pipeline)
The pipeline to use for this command.
ISize GetRenderTargetSize() const
virtual void SetInstanceCount(size_t count)
virtual fml::Status Draw()
Record the currently pending command.
virtual void SetCommandLabel(std::string_view label)
The debugging label to use for the command.
a wrapper around the impeller [Allocator] instance that can be used to provide caching of allocated r...
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 Matrix MakeRotationY(Radians r)
static Matrix MakePerspective(Radians fov_y, Scalar aspect_ratio, Scalar z_near, Scalar z_far)
static Matrix MakeRotationZ(Radians r)
static constexpr Matrix MakeScale(const Vector3 &s)
static Matrix MakeRotationX(Radians r)
An optional (but highly recommended) utility for creating pipelines from reflected shader information...
static std::optional< PipelineDescriptor > MakeDefaultPipelineDescriptor(const Context &context, const std::vector< Scalar > &constants={})
Create a default pipeline descriptor using the combination reflected shader information....
SamplerAddressMode width_address_mode
SamplerAddressMode height_address_mode
CompareFunction stencil_compare
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...
std::shared_ptr< const fml::Mapping > data