Flutter Impeller
compiler_unittests.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <cstring>
6 #include "flutter/testing/testing.h"
7 #include "gtest/gtest.h"
13 
14 namespace impeller {
15 namespace compiler {
16 namespace testing {
17 
18 TEST(CompilerTest, Defines) {
19  std::shared_ptr<const fml::Mapping> fixture =
20  flutter::testing::OpenFixtureAsMapping("check_gles_definition.frag");
21 
22  SourceOptions options;
25  options.entry_point_name = "main";
27 
28  Reflector::Options reflector_options;
30  Compiler compiler = Compiler(fixture, options, reflector_options);
31 
32  // Should fail as the shader has a compilation error in it.
33  EXPECT_EQ(compiler.GetSPIRVAssembly(), nullptr);
34 
35  // Should succeed as the compilation error is ifdef'd out.
38  Compiler compiler_2 = Compiler(fixture, options, reflector_options);
39  EXPECT_NE(compiler_2.GetSPIRVAssembly(), nullptr);
40 }
41 
42 TEST(CompilerTest, ShaderKindMatchingIsSuccessful) {
43  ASSERT_EQ(SourceTypeFromFileName("hello.vert"), SourceType::kVertexShader);
44  ASSERT_EQ(SourceTypeFromFileName("hello.frag"), SourceType::kFragmentShader);
45  ASSERT_EQ(SourceTypeFromFileName("hello.comp"), SourceType::kComputeShader);
46  ASSERT_EQ(SourceTypeFromFileName("hello.msl"), SourceType::kUnknown);
47  ASSERT_EQ(SourceTypeFromFileName("hello.glsl"), SourceType::kUnknown);
48 }
49 
50 TEST_P(CompilerTest, CanCompile) {
51  if (GetParam() == TargetPlatform::kSkSL) {
52  GTEST_SKIP() << "Not supported with SkSL";
53  }
54  ASSERT_TRUE(CanCompileAndReflect("sample.vert"));
55  ASSERT_TRUE(CanCompileAndReflect("sample.vert", SourceType::kVertexShader));
56  ASSERT_TRUE(CanCompileAndReflect("sample.vert", SourceType::kVertexShader,
58 }
59 
60 TEST_P(CompilerTest, CanCompileHLSL) {
61  if (GetParam() == TargetPlatform::kSkSL) {
62  GTEST_SKIP() << "Not supported with SkSL";
63  }
64  ASSERT_TRUE(CanCompileAndReflect(
65  "simple.vert.hlsl", SourceType::kVertexShader, SourceLanguage::kHLSL));
66 }
67 
68 TEST_P(CompilerTest, CanCompileHLSLWithMultipleStages) {
69  if (GetParam() == TargetPlatform::kSkSL) {
70  GTEST_SKIP() << "Not supported with SkSL";
71  }
72  ASSERT_TRUE(CanCompileAndReflect("multiple_stages.hlsl",
74  SourceLanguage::kHLSL, "VertexShader"));
75  ASSERT_TRUE(CanCompileAndReflect("multiple_stages.hlsl",
77  SourceLanguage::kHLSL, "FragmentShader"));
78 }
79 
80 TEST_P(CompilerTest, CanCompileComputeShader) {
81  if (!TargetPlatformIsMetal(GetParam())) {
82  GTEST_SKIP()
83  << "Only enabled on Metal backends till ES 3.2 support is added.";
84  }
85  ASSERT_TRUE(CanCompileAndReflect("sample.comp"));
86  ASSERT_TRUE(CanCompileAndReflect("sample.comp", SourceType::kComputeShader));
87 }
88 
89 TEST_P(CompilerTest, MustFailDueToExceedingResourcesLimit) {
90  if (GetParam() == TargetPlatform::kSkSL) {
91  GTEST_SKIP() << "Not supported with SkSL";
92  }
93  ScopedValidationDisable disable_validation;
94  ASSERT_FALSE(
95  CanCompileAndReflect("resources_limit.vert", SourceType::kVertexShader));
96 }
97 
98 TEST_P(CompilerTest, MustFailDueToMultipleLocationPerStructMember) {
99  if (GetParam() == TargetPlatform::kSkSL) {
100  GTEST_SKIP() << "Not supported with SkSL";
101  }
102  ScopedValidationDisable disable_validation;
103  ASSERT_FALSE(CanCompileAndReflect("struct_def_bug.vert"));
104 }
105 
106 TEST_P(CompilerTest, BindingBaseForFragShader) {
107  if (!TargetPlatformIsVulkan(GetParam())) {
108  GTEST_SKIP();
109  }
110 
111  ASSERT_TRUE(CanCompileAndReflect("sample.vert", SourceType::kVertexShader));
112  ASSERT_TRUE(CanCompileAndReflect("sample.frag", SourceType::kFragmentShader));
113 
114  auto get_binding = [&](const char* fixture) -> uint32_t {
115  auto json_fd = GetReflectionJson(fixture);
116  nlohmann::json shader_json = nlohmann::json::parse(json_fd->GetMapping());
117  return shader_json["buffers"][0]["binding"].get<uint32_t>();
118  };
119 
120  auto vert_uniform_binding = get_binding("sample.vert");
121  auto frag_uniform_binding = get_binding("sample.frag");
122 
123  ASSERT_GT(frag_uniform_binding, vert_uniform_binding);
124 }
125 
126 TEST_P(CompilerTest, UniformsHaveBindingAndSet) {
127  if (GetParam() == TargetPlatform::kSkSL) {
128  GTEST_SKIP() << "Not supported with SkSL";
129  }
130  ASSERT_TRUE(CanCompileAndReflect("sample_with_binding.vert",
132  ASSERT_TRUE(CanCompileAndReflect("sample.frag", SourceType::kFragmentShader));
133 
134  struct binding_and_set {
135  uint32_t binding;
136  uint32_t set;
137  };
138 
139  auto get_binding = [&](const char* fixture) -> binding_and_set {
140  auto json_fd = GetReflectionJson(fixture);
141  nlohmann::json shader_json = nlohmann::json::parse(json_fd->GetMapping());
142  uint32_t binding = shader_json["buffers"][0]["binding"].get<uint32_t>();
143  uint32_t set = shader_json["buffers"][0]["set"].get<uint32_t>();
144  return {binding, set};
145  };
146 
147  auto vert_uniform_binding = get_binding("sample_with_binding.vert");
148  auto frag_uniform_binding = get_binding("sample.frag");
149 
150  ASSERT_EQ(frag_uniform_binding.set, 0u);
151  ASSERT_EQ(vert_uniform_binding.set, 3u);
152  ASSERT_EQ(vert_uniform_binding.binding, 17u);
153 }
154 
155 TEST_P(CompilerTest, SkSLTextureLookUpOrderOfOperations) {
156  if (GetParam() != TargetPlatform::kSkSL) {
157  GTEST_SKIP() << "Only supported on SkSL";
158  }
159  ASSERT_TRUE(
160  CanCompileAndReflect("texture_lookup.frag", SourceType::kFragmentShader));
161 
162  auto shader = GetShaderFile("texture_lookup.frag", GetParam());
163  std::string_view shader_mapping(
164  reinterpret_cast<const char*>(shader->GetMapping()), shader->GetSize());
165 
166  constexpr std::string_view expected =
167  "textureA.eval(textureA_size * ( vec2(1.0) + flutter_FragCoord.xy));";
168 
169  EXPECT_NE(shader_mapping.find(expected), std::string::npos);
170 }
171 
172 TEST_P(CompilerTest, CanCompileStructs) {
173  if (GetParam() != TargetPlatform::kSkSL) {
174  GTEST_SKIP() << "Only supported on SkSL";
175  }
176  ASSERT_TRUE(CanCompileAndReflect("struct_internal.frag",
178 }
179 
180 #define INSTANTIATE_TARGET_PLATFORM_TEST_SUITE_P(suite_name) \
181  INSTANTIATE_TEST_SUITE_P( \
182  suite_name, CompilerTest, \
183  ::testing::Values(TargetPlatform::kOpenGLES, \
184  TargetPlatform::kOpenGLDesktop, \
185  TargetPlatform::kMetalDesktop, \
186  TargetPlatform::kMetalIOS, TargetPlatform::kSkSL), \
187  [](const ::testing::TestParamInfo<CompilerTest::ParamType>& info) { \
188  return TargetPlatformToString(info.param); \
189  });
190 
192 
193 } // namespace testing
194 } // namespace compiler
195 } // namespace impeller
std::shared_ptr< fml::Mapping > GetSPIRVAssembly() const
Definition: compiler.cc:486
INSTANTIATE_TARGET_PLATFORM_TEST_SUITE_P(CompilerSuite)
TEST_P(CompilerTest, CanCompile)
TEST(CompilerTest, Defines)
SourceType SourceTypeFromFileName(const std::string &file_name)
Definition: types.cc:30
bool TargetPlatformIsMetal(TargetPlatform platform)
Definition: types.cc:290
bool TargetPlatformIsVulkan(TargetPlatform platform)
Definition: types.cc:309