8 #include "flutter/fml/make_copyable.h"
9 #include "flutter/testing/testing.h"
10 #include "gmock/gmock.h"
11 #include "gtest/gtest.h"
16 #include "impeller/entity/runtime_effect.vert.h"
23 #include "impeller/runtime_stage/runtime_stage_flatbuffers.h"
25 #include "runtime_stage_types_flatbuffers.h"
26 #include "third_party/abseil-cpp/absl/status/status_matchers.h"
35 const std::shared_ptr<fml::Mapping> fixture =
36 flutter::testing::OpenFixtureAsMapping(
"ink_sparkle.frag.iplr");
38 ASSERT_GT(fixture->GetSize(), 0u);
40 ABSL_ASSERT_OK(stages);
47 flatbuffers::FlatBufferBuilder builder;
48 fb::RuntimeStagesBuilder stages_builder(builder);
49 stages_builder.add_format_version(0);
50 auto stages = stages_builder.Finish();
51 builder.Finish(stages, fb::RuntimeStagesIdentifier());
52 auto mapping = std::make_shared<fml::NonOwnedMapping>(
53 builder.GetBufferPointer(), builder.GetSize());
55 EXPECT_FALSE(runtime_stages.ok());
56 EXPECT_EQ(runtime_stages.status().code(), absl::StatusCode::kInvalidArgument);
61 const std::shared_ptr<fml::Mapping> fixture =
62 flutter::testing::OpenFixtureAsMapping(
"ink_sparkle.frag.iplr");
64 auto junk_allocation = std::make_shared<Allocation>();
65 ASSERT_TRUE(junk_allocation->Truncate(
Bytes{fixture->GetSize()},
false));
68 ::memset(junk_allocation->GetBuffer(), 127,
69 junk_allocation->GetLength().GetByteSize());
72 ASSERT_FALSE(stages.ok());
80 auto data = std::make_shared<std::vector<uint8_t>>(32, 0);
89 auto mapping = std::make_shared<fml::NonOwnedMapping>(
90 data->data(), data->size(), [data](
auto,
auto) {});
92 ASSERT_FALSE(stages.ok());
93 EXPECT_EQ(stages.status().code(), absl::StatusCode::kInvalidArgument);
97 const std::shared_ptr<fml::Mapping> fixture =
98 flutter::testing::OpenFixtureAsMapping(
99 "all_supported_uniforms.frag.iplr");
100 ASSERT_TRUE(fixture);
101 ASSERT_GT(fixture->GetSize(), 0u);
103 ABSL_ASSERT_OK(stages);
107 switch (GetBackend()) {
115 ASSERT_EQ(stage->GetUniforms().size(), 14u);
118 auto uni = stage->GetUniform(
"uFloat");
119 ASSERT_NE(uni,
nullptr);
120 EXPECT_EQ(uni->dimensions.rows, 1u);
121 EXPECT_EQ(uni->dimensions.cols, 1u);
122 EXPECT_EQ(uni->location, 0u);
124 EXPECT_TRUE(uni->padding_layout.empty());
128 auto uni = stage->GetUniform(
"uVec2");
129 ASSERT_NE(uni,
nullptr);
130 EXPECT_EQ(uni->dimensions.rows, 2u);
131 EXPECT_EQ(uni->dimensions.cols, 1u);
132 EXPECT_EQ(uni->location, 1u);
134 EXPECT_TRUE(uni->padding_layout.empty());
138 auto uni = stage->GetUniform(
"uVec3");
139 ASSERT_NE(uni,
nullptr);
140 EXPECT_EQ(uni->dimensions.rows, 3u);
141 EXPECT_EQ(uni->dimensions.cols, 1u);
142 EXPECT_EQ(uni->location, 2u);
144 auto padding = uni->padding_layout;
158 auto uni = stage->GetUniform(
"uVec4");
159 ASSERT_NE(uni,
nullptr);
160 EXPECT_EQ(uni->dimensions.rows, 4u);
161 EXPECT_EQ(uni->dimensions.cols, 1u);
162 EXPECT_EQ(uni->location, 3u);
164 EXPECT_TRUE(uni->padding_layout.empty());
168 auto uni = stage->GetUniform(
"uMat2");
169 ASSERT_NE(uni,
nullptr);
170 EXPECT_EQ(uni->dimensions.rows, 2u);
171 EXPECT_EQ(uni->dimensions.cols, 2u);
172 EXPECT_EQ(uni->location, 4u);
174 EXPECT_TRUE(uni->padding_layout.empty());
178 auto uni = stage->GetUniform(
"uMat3");
179 ASSERT_NE(uni,
nullptr);
180 EXPECT_EQ(uni->dimensions.rows, 3u);
181 EXPECT_EQ(uni->dimensions.cols, 3u);
182 EXPECT_EQ(uni->location, 5u);
187 auto uni = stage->GetUniform(
"uMat4");
188 ASSERT_NE(uni,
nullptr);
189 EXPECT_EQ(uni->dimensions.rows, 4u);
190 EXPECT_EQ(uni->dimensions.cols, 4u);
191 EXPECT_EQ(uni->location, 6u);
193 EXPECT_TRUE(uni->padding_layout.empty());
197 auto uni = stage->GetUniform(
"uFloatArray");
198 ASSERT_NE(uni,
nullptr);
199 EXPECT_EQ(uni->dimensions.rows, 1u);
200 EXPECT_EQ(uni->dimensions.cols, 1u);
201 EXPECT_EQ(uni->location, 7u);
203 EXPECT_TRUE(uni->padding_layout.empty());
206 auto uni = stage->GetUniform(
"uVec2Array");
207 ASSERT_NE(uni,
nullptr);
208 EXPECT_EQ(uni->dimensions.rows, 2u);
209 EXPECT_EQ(uni->dimensions.cols, 1u);
210 EXPECT_EQ(uni->location, 9u);
212 EXPECT_TRUE(uni->padding_layout.empty());
216 auto uni = stage->GetUniform(
"uVec3Array");
217 ASSERT_NE(uni,
nullptr);
218 EXPECT_EQ(uni->dimensions.rows, 3u);
219 EXPECT_EQ(uni->dimensions.cols, 1u);
220 EXPECT_EQ(uni->location, 11u);
225 auto uni = stage->GetUniform(
"uVec4Array");
226 ASSERT_NE(uni,
nullptr);
227 EXPECT_EQ(uni->dimensions.rows, 4u);
228 EXPECT_EQ(uni->dimensions.cols, 1u);
229 EXPECT_EQ(uni->location, 13u);
231 EXPECT_TRUE(uni->padding_layout.empty());
235 auto uni = stage->GetUniform(
"uMat2Array");
236 ASSERT_NE(uni,
nullptr);
237 EXPECT_EQ(uni->dimensions.rows, 2u);
238 EXPECT_EQ(uni->dimensions.cols, 2u);
239 EXPECT_EQ(uni->location, 15u);
241 EXPECT_TRUE(uni->padding_layout.empty());
245 auto uni = stage->GetUniform(
"uMat3Array");
246 ASSERT_NE(uni,
nullptr);
247 EXPECT_EQ(uni->dimensions.rows, 3u);
248 EXPECT_EQ(uni->dimensions.cols, 3u);
249 EXPECT_EQ(uni->location, 17u);
254 auto uni = stage->GetUniform(
"uMat4Array");
255 ASSERT_NE(uni,
nullptr);
256 EXPECT_EQ(uni->dimensions.rows, 4u);
257 EXPECT_EQ(uni->dimensions.cols, 4u);
258 EXPECT_EQ(uni->location, 19u);
260 EXPECT_TRUE(uni->padding_layout.empty());
265 EXPECT_EQ(stage->GetUniforms().size(), 1u);
273 std::vector<RuntimePaddingType> layout(uni->
GetGPUSize() /
sizeof(
float),
335 EXPECT_THAT(uni->
padding_layout, ::testing::ElementsAreArray(layout));
337 std::vector<std::pair<std::string, unsigned int>> expected_uniforms = {
338 {
"uFloat", 4}, {
"uVec2", 8}, {
"uVec3", 12},
339 {
"uVec4", 16}, {
"uMat2", 16}, {
"uMat3", 36},
340 {
"uMat4", 64}, {
"uFloatArray", 8}, {
"uVec2Array", 16},
341 {
"uVec3Array", 24}, {
"uVec4Array", 32}, {
"uMat2Array", 32},
342 {
"uMat3Array", 72}, {
"uMat4Array", 128}};
344 ASSERT_EQ(uni->
struct_fields.size(), expected_uniforms.size());
346 for (
size_t i = 0; i < expected_uniforms.size(); ++i) {
348 const auto& expected = expected_uniforms[i];
350 EXPECT_EQ(element.name, expected.first) <<
"index: " << i;
351 EXPECT_EQ(element.byte_size, expected.second) <<
"index: " << i;
360 GTEST_SKIP() <<
"Test only relevant for Vulkan";
362 const std::shared_ptr<fml::Mapping> fixture =
363 flutter::testing::OpenFixtureAsMapping(
364 "uniforms_and_sampler_1.frag.iplr");
365 ASSERT_TRUE(fixture);
366 ASSERT_GT(fixture->GetSize(), 0u);
368 ABSL_ASSERT_OK(stages);
371 EXPECT_EQ(stage->GetUniforms().size(), 2u);
376 EXPECT_EQ(uni->binding, 65u);
379 auto sampler_uniform = stage->GetUniform(
"u_texture");
381 EXPECT_EQ(sampler_uniform->binding, 64u);
386 GTEST_SKIP() <<
"Test only relevant for Vulkan";
388 const std::shared_ptr<fml::Mapping> fixture =
389 flutter::testing::OpenFixtureAsMapping(
390 "uniforms_and_sampler_2.frag.iplr");
391 ASSERT_TRUE(fixture);
392 ASSERT_GT(fixture->GetSize(), 0u);
394 ABSL_ASSERT_OK(stages);
397 EXPECT_EQ(stage->GetUniforms().size(), 2u);
402 EXPECT_EQ(uni->binding, 64u);
405 auto sampler_uniform = stage->GetUniform(
"u_texture");
407 EXPECT_EQ(sampler_uniform->binding, 65u);
411 const std::shared_ptr<fml::Mapping> fixture =
412 flutter::testing::OpenFixtureAsMapping(
"ink_sparkle.frag.iplr");
413 ASSERT_TRUE(fixture);
414 ASSERT_GT(fixture->GetSize(), 0u);
416 ABSL_ASSERT_OK(stages);
419 std::promise<bool> registration;
420 auto future = registration.get_future();
421 auto library = GetContext()->GetShaderLibrary();
422 library->RegisterFunction(
423 stage->GetEntrypoint(),
425 stage->GetCodeMapping(),
426 fml::MakeCopyable([reg = std::move(registration)](
bool result)
mutable {
427 reg.set_value(result);
429 ASSERT_TRUE(future.get());
433 ASSERT_NE(
function,
nullptr);
442 ASSERT_EQ(
function,
nullptr);
447 auto stages_result = OpenAssetAsRuntimeStage(
"ink_sparkle.frag.iplr");
448 ABSL_ASSERT_OK(stages_result);
452 ASSERT_NE(stage,
nullptr);
453 ASSERT_TRUE(RegisterStage(*stage));
454 auto library = GetContext()->GetShaderLibrary();
455 using VS = RuntimeEffectVertexShader;
457 desc.
SetLabel(
"Runtime Stage InkSparkle");
462 auto vertex_descriptor = std::make_shared<VertexDescriptor>();
463 vertex_descriptor->SetStageInputs(VS::kAllShaderStageInputs,
464 VS::kInterleavedBufferLayout);
466 std::array<DescriptorSetLayout, 2> descriptor_set_layouts = {
467 VS::kDescriptorSetLayouts[0],
474 vertex_descriptor->RegisterDescriptorSetLayouts(descriptor_set_layouts);
478 color0.
format = GetContext()->GetCapabilities()->GetDefaultColorFormat();
483 const auto stencil_fmt =
484 GetContext()->GetCapabilities()->GetDefaultStencilFormat();
486 auto pipeline = GetContext()->GetPipelineLibrary()->GetPipeline(desc).Get();
491 auto stages_result = OpenAssetAsRuntimeStage(
"ink_sparkle.frag.iplr");
492 ABSL_ASSERT_OK(stages_result);
493 auto stages = stages_result.value();
502 OpenAssetAsRuntimeStage(
"runtime_stage_simple_no_sksl.frag.iplr");
503 ABSL_ASSERT_OK(stages_result);
504 auto stages = stages_result.value();
511 TEST(ShaderKeyTest, MakeUserScopedNameProducesScopedString) {
513 "assets/foo.frag",
"main"),
514 "re:assets/foo.frag:main");
518 "packages/pkg_a/assets/shaders.shaderbundle",
519 "solid_fill_fragment_main"),
520 "fg:packages/pkg_a/assets/shaders.shaderbundle:solid_fill_fragment_main");
523 TEST(ShaderKeyTest, MakeUserScopedNameContainsColonSeparator) {
529 EXPECT_NE(scoped.find(
':'), std::string::npos);
532 TEST(ShaderKeyTest, MakeUserScopedNameDifferentLibraryIdsDoNotCollide) {
543 TEST(ShaderKeyTest, MakeUserScopedNameDifferentScopesDoNotCollide) {
550 EXPECT_NE(runtime_effect, flutter_gpu);
553 TEST(ShaderKeyTest, MakeUserScopedNameHandlesLongInputs) {
558 const std::string long_library_id(4096,
'a');
559 const std::string long_entrypoint(2048,
'b');
563 long_library_id.size() + 1 +
564 long_entrypoint.size());
565 EXPECT_EQ(scoped.substr(0, 3),
"fg:");
566 EXPECT_EQ(scoped.substr(3, long_library_id.size()), long_library_id);
567 EXPECT_EQ(scoped.substr(3 + long_library_id.size(), 1),
":");
568 EXPECT_EQ(scoped.substr(3 + long_library_id.size() + 1), long_entrypoint);
575 const std::shared_ptr<fml::Mapping> fixture =
576 flutter::testing::OpenFixtureAsMapping(
"ink_sparkle.frag.iplr");
577 ASSERT_TRUE(fixture);
579 ABSL_ASSERT_OK(stages_a);
581 ABSL_ASSERT_OK(stages_b);
584 ASSERT_TRUE(stage_a);
585 ASSERT_TRUE(stage_b);
586 EXPECT_FALSE(stage_a->GetLibraryId().empty());
587 EXPECT_FALSE(stage_b->GetLibraryId().empty());
588 EXPECT_NE(stage_a->GetLibraryId(), stage_b->GetLibraryId());
595 const std::shared_ptr<fml::Mapping> fixture =
596 flutter::testing::OpenFixtureAsMapping(
"ink_sparkle.frag.iplr");
597 ASSERT_TRUE(fixture);
599 ABSL_ASSERT_OK(stages);
602 stage->SetLibraryId(
"packages/my_pkg/assets/shader.frag");
603 EXPECT_EQ(stage->GetLibraryId(),
"packages/my_pkg/assets/shader.frag");
PipelineDescriptor & SetStencilPixelFormat(PixelFormat format)
PipelineDescriptor & SetVertexDescriptor(std::shared_ptr< VertexDescriptor > vertex_descriptor)
PipelineDescriptor & AddStageEntrypoint(std::shared_ptr< const ShaderFunction > function)
PipelineDescriptor & SetLabel(std::string_view label)
PipelineDescriptor & SetStencilAttachmentDescriptors(std::optional< StencilAttachmentDescriptor > front_and_back)
PipelineDescriptor & SetColorAttachmentDescriptor(size_t index, ColorAttachmentDescriptor desc)
static const char * kVulkanUBOName
static absl::StatusOr< Map > DecodeRuntimeStages(const std::shared_ptr< fml::Mapping > &payload)
Vector2 padding
The halo padding in source space.
static std::optional< RuntimeStageBackend > GetRuntimeStageBackend(TargetPlatform target_platform)
TEST(AllocationSizeTest, CanCreateTypedAllocations)
TEST_P(AiksTest, DrawAtlasNoColor)
INSTANTIATE_PLAYGROUND_SUITE(AiksTest)
constexpr ShaderStage ToShaderStage(RuntimeShaderStage stage)
@ kEqual
Comparison test passes if new_value == current_value.
std::shared_ptr< fml::Mapping > CreateMappingFromAllocation(const std::shared_ptr< Allocation > &allocation)
Creates a mapping from allocation.
LinePipeline::VertexShader VS
std::shared_ptr< PipelineGLES > pipeline
Describe the color attachment that will be used with this pipeline.
static constexpr std::string_view kScopeFlutterGPU
Scope tag for Flutter GPU user shader bundles.
static std::string MakeUserScopedName(std::string_view scope, std::string_view library_id, std::string_view entrypoint)
static constexpr std::string_view kScopeRuntimeEffect
CompareFunction stencil_compare