| 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"
8 #include "impeller/base/validation.h"
9 #include "impeller/compiler/compiler.h"
10 #include "impeller/compiler/compiler_test.h"
11 #include "impeller/compiler/source_options.h"
12 #include "impeller/compiler/types.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;
23 options.source_language = SourceLanguage::kGLSL;
24 options.target_platform = TargetPlatform::kRuntimeStageGLES;
25 options.entry_point_name = "main";
26 options.type = SourceType::kFragmentShader;
27
28 Reflector::Options reflector_options;
29 reflector_options.target_platform = TargetPlatform::kRuntimeStageGLES;
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.
36 options.target_platform = TargetPlatform::kRuntimeStageVulkan;
37 reflector_options.target_platform = TargetPlatform::kRuntimeStageVulkan;
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,
57 SourceLanguage::kGLSL));
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",
73 SourceType::kVertexShader,
74 SourceLanguage::kHLSL, "VertexShader"));
75 ASSERT_TRUE(CanCompileAndReflect("multiple_stages.hlsl",
76 SourceType::kFragmentShader,
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",
131 SourceType::kVertexShader));
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",
177 SourceType::kFragmentShader));
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
191 INSTANTIATE_TARGET_PLATFORM_TEST_SUITE_P(CompilerSuite);
192
193 } // namespace testing
194 } // namespace compiler
195 } // namespace impeller
impeller::compiler::Compiler
Definition: compiler.h:24
impeller::compiler::Compiler::GetSPIRVAssembly
std::shared_ptr< fml::Mapping > GetSPIRVAssembly() const
Definition: compiler.cc:486
impeller::compiler::testing::CompilerTest
Definition: compiler_test.h:18
types.h
compiler.h
compiler_test.h
impeller::compiler::testing::INSTANTIATE_TARGET_PLATFORM_TEST_SUITE_P
INSTANTIATE_TARGET_PLATFORM_TEST_SUITE_P(CompilerSuite)
impeller::compiler::testing::TEST_P
TEST_P(CompilerTest, CanCompile)
Definition: compiler_unittests.cc:50
impeller::compiler::testing::TEST
TEST(CompilerTest, Defines)
Definition: compiler_unittests.cc:18
impeller::compiler::SourceType::kUnknown
@ kUnknown
impeller::compiler::SourceType::kFragmentShader
@ kFragmentShader
impeller::compiler::SourceType::kVertexShader
@ kVertexShader
impeller::compiler::SourceType::kComputeShader
@ kComputeShader
impeller::compiler::SourceLanguage::kGLSL
@ kGLSL
impeller::compiler::SourceLanguage::kHLSL
@ kHLSL
impeller::compiler::SourceTypeFromFileName
SourceType SourceTypeFromFileName(const std::string &file_name)
Definition: types.cc:30
impeller::compiler::TargetPlatformIsMetal
bool TargetPlatformIsMetal(TargetPlatform platform)
Definition: types.cc:290
impeller::compiler::TargetPlatformIsVulkan
bool TargetPlatformIsVulkan(TargetPlatform platform)
Definition: types.cc:309
impeller::compiler::TargetPlatform::kRuntimeStageVulkan
@ kRuntimeStageVulkan
impeller::compiler::TargetPlatform::kSkSL
@ kSkSL
impeller::compiler::TargetPlatform::kRuntimeStageGLES
@ kRuntimeStageGLES
impeller
Definition: allocation.cc:12
source_options.h
impeller::ScopedValidationDisable
Definition: validation.h:56
impeller::compiler::Reflector::Options
Definition: reflector.h:146
impeller::compiler::Reflector::Options::target_platform
TargetPlatform target_platform
Definition: reflector.h:147
impeller::compiler::SourceOptions
Definition: source_options.h:20
impeller::compiler::SourceOptions::source_language
SourceLanguage source_language
Definition: source_options.h:23
impeller::compiler::SourceOptions::entry_point_name
std::string entry_point_name
Definition: source_options.h:27
impeller::compiler::SourceOptions::target_platform
TargetPlatform target_platform
Definition: source_options.h:22
impeller::compiler::SourceOptions::type
SourceType type
Definition: source_options.h:21
validation.h