7#include "gtest/gtest.h"
26 [](const ::testing::TestParamInfo<CompilerTest::ParamType>& info) {
38 [](const ::testing::TestParamInfo<CompilerTest::ParamType>& info) {
46 [](const ::testing::TestParamInfo<CompilerTest::ParamType>& info) {
54 [](const ::testing::TestParamInfo<CompilerTest::ParamType>& info) {
59 std::shared_ptr<const fml::Mapping> fixture =
91 ASSERT_TRUE(CanCompileAndReflect(
"sample.vert"));
98 ASSERT_TRUE(CanCompileAndReflect(
103 ASSERT_TRUE(CanCompileAndReflect(
"multiple_stages.hlsl",
106 ASSERT_TRUE(CanCompileAndReflect(
"multiple_stages.hlsl",
114 <<
"Only enabled on Metal backends till ES 3.2 support is added.";
116 ASSERT_TRUE(CanCompileAndReflect(
"sample.comp"));
128 ASSERT_FALSE(CanCompileAndReflect(
"struct_def_bug.vert"));
133 GTEST_SKIP() <<
"Only GL targets lower uniform blocks to flat structs.";
139 auto sl_source = GetCompiler()->GetSLShaderSource();
140 ASSERT_NE(sl_source,
nullptr);
141 const std::string source(
142 reinterpret_cast<const char*
>(sl_source->GetMapping()),
143 sl_source->GetSize());
144 EXPECT_EQ(source.find(
"uParams."), std::string::npos) << source;
145 EXPECT_NE(source.find(
"_Params."), std::string::npos) << source;
156 auto get_binding = [&](
const char* fixture) -> uint32_t {
157 auto json_fd = GetReflectionJson(fixture);
158 nlohmann::json shader_json = nlohmann::json::parse(json_fd->GetMapping());
159 return shader_json[
"buffers"][0][
"binding"].get<uint32_t>();
162 auto vert_uniform_binding = get_binding(
"sample.vert");
163 auto frag_uniform_binding = get_binding(
"sample.frag");
165 ASSERT_GT(frag_uniform_binding, vert_uniform_binding);
176 static UniformInfo fromJson(
const nlohmann::json& json) {
178 .uniform_name = json[
"name"].get<std::string>(),
179 .
location = json[
"location"].get<uint32_t>(),
180 .type_name = json[
"type"][
"type_name"].get<std::string>(),
181 .
columns = json[
"type"][
"columns"].get<uint32_t>(),
182 .vec_size = json[
"type"][
"vec_size"].get<uint32_t>(),
186 static UniformInfo
Sampler(
const std::string&
name, uint32_t location) {
188 .uniform_name =
name,
190 .type_name =
"ShaderType::kSampledImage",
195 static UniformInfo Float(
const std::string&
name, uint32_t location) {
196 return FloatInfo(
name, location, 1u, 1u);
198 static UniformInfo Vec2(
const std::string&
name, uint32_t location) {
199 return FloatInfo(
name, location, 1u, 2u);
201 static UniformInfo Vec3(
const std::string&
name, uint32_t location) {
202 return FloatInfo(
name, location, 1u, 3u);
204 static UniformInfo Vec4(
const std::string&
name, uint32_t location) {
205 return FloatInfo(
name, location, 1u, 4u);
207 static UniformInfo Mat4(
const std::string&
name, uint32_t location) {
208 return FloatInfo(
name, location, 4u, 4u);
211 constexpr bool operator==(
const UniformInfo& other)
const {
212 return (uniform_name == other.uniform_name &&
213 location == other.location &&
214 type_name == other.type_name &&
215 columns == other.columns &&
216 vec_size == other.vec_size);
220 static UniformInfo FloatInfo(
const std::string&
name,
225 .uniform_name =
name,
227 .type_name =
"ShaderType::kFloat",
234inline std::ostream&
operator<<(std::ostream& out,
const UniformInfo& info) {
235 out <<
"UniformInfo {" << std::endl
236 <<
" uniform_name: " << info.uniform_name << std::endl
237 <<
" location: " << info.location << std::endl
238 <<
" type_name: " << info.type_name << std::endl
239 <<
" columns: " << info.columns << std::endl
240 <<
" vec_size: " << info.vec_size << std::endl
250 GTEST_SKIP() <<
"Not supported with Vulkan";
253 ASSERT_TRUE(CanCompileAndReflect(
"sample_with_uniforms.frag",
257 auto json_fd = GetReflectionJson(
"sample_with_uniforms.frag");
258 ASSERT_TRUE(json_fd);
259 nlohmann::json shader_json = nlohmann::json::parse(json_fd->GetMapping());
260 auto sampler_list = shader_json[
"sampled_images"];
261 auto float_list = shader_json[
"uniforms"];
262 ASSERT_EQ(sampler_list.size(), 2u);
263 ASSERT_EQ(float_list.size(), 6u);
267 std::array expected_infos = {
268 UniformInfo::Sampler(
"uFirstSampler", 1u),
269 UniformInfo::Sampler(
"uSampler", 7u),
272 ASSERT_EQ(sampler_list.size(), expected_infos.size());
273 for (
size_t i = 0;
i < expected_infos.size();
i++) {
274 EXPECT_EQ(UniformInfo::fromJson(sampler_list[
i]), expected_infos[
i])
281 std::array expected_infos = {
282 UniformInfo::Float(
"uFirstFloat", 0u),
283 UniformInfo::Float(
"uFloat", 2u),
284 UniformInfo::Vec2(
"uVec2", 3u),
285 UniformInfo::Vec3(
"uVec3", 4u),
286 UniformInfo::Vec4(
"uVec4", 5u),
287 UniformInfo::Mat4(
"uMat4", 6u),
290 ASSERT_EQ(float_list.size(), expected_infos.size());
291 for (
size_t i = 0;
i < expected_infos.size();
i++) {
292 EXPECT_EQ(UniformInfo::fromJson(float_list[
i]), expected_infos[
i])
302 GTEST_SKIP() <<
"Not supported with Vulkan";
305 ASSERT_TRUE(CanCompileAndReflect(
"sample_with_positioned_uniforms.frag",
309 auto json_fd = GetReflectionJson(
"sample_with_positioned_uniforms.frag");
310 ASSERT_TRUE(json_fd);
311 nlohmann::json shader_json = nlohmann::json::parse(json_fd->GetMapping());
312 auto sampler_list = shader_json[
"sampled_images"];
313 auto float_list = shader_json[
"uniforms"];
314 ASSERT_EQ(sampler_list.size(), 3u);
315 ASSERT_EQ(float_list.size(), 7u);
319 std::array expected_infos = {
320 UniformInfo::Sampler(
"uSamplerNotPositioned1", 1u),
321 UniformInfo::Sampler(
"uSampler", 0u),
322 UniformInfo::Sampler(
"uSamplerNotPositioned2", 3u),
325 ASSERT_EQ(sampler_list.size(), expected_infos.size());
326 for (
size_t i = 0;
i < expected_infos.size();
i++) {
327 EXPECT_EQ(UniformInfo::fromJson(sampler_list[
i]), expected_infos[
i])
334 std::array expected_infos = {
335 UniformInfo::Float(
"uFloatNotPositioned1", 0u),
336 UniformInfo::Float(
"uFloat", 6u),
337 UniformInfo::Vec2(
"uVec2", 5u),
338 UniformInfo::Vec3(
"uVec3", 3u),
339 UniformInfo::Vec4(
"uVec4", 2u),
340 UniformInfo::Mat4(
"uMat4", 1u),
341 UniformInfo::Float(
"uFloatNotPositioned2", 2u),
344 ASSERT_EQ(float_list.size(), expected_infos.size());
345 for (
size_t i = 0;
i < expected_infos.size();
i++) {
346 EXPECT_EQ(UniformInfo::fromJson(float_list[
i]), expected_infos[
i])
354 GTEST_SKIP() <<
"Not supported with SkSL";
356 ASSERT_TRUE(CanCompileAndReflect(
"sample_with_binding.vert",
360 struct binding_and_set {
365 auto get_binding = [&](
const char* fixture) -> binding_and_set {
366 auto json_fd = GetReflectionJson(fixture);
367 nlohmann::json shader_json = nlohmann::json::parse(json_fd->GetMapping());
368 uint32_t binding = shader_json[
"buffers"][0][
"binding"].get<uint32_t>();
369 uint32_t set = shader_json[
"buffers"][0][
"set"].get<uint32_t>();
370 return {binding, set};
373 auto vert_uniform_binding = get_binding(
"sample_with_binding.vert");
374 auto frag_uniform_binding = get_binding(
"sample.frag");
376 ASSERT_EQ(frag_uniform_binding.set, 0u);
377 ASSERT_EQ(vert_uniform_binding.set, 3u);
378 ASSERT_EQ(vert_uniform_binding.binding, 17u);
385 auto shader = GetShaderFile(
"texture_lookup.frag", GetParam());
386 std::string_view shader_mapping(
387 reinterpret_cast<const char*
>(shader->GetMapping()), shader->GetSize());
389 constexpr std::string_view expected =
390 "textureA.eval(textureA_size * ( vec2(1.0) + flutter_FragCoord.xy));";
392 EXPECT_NE(shader_mapping.find(expected), std::string::npos);
396 ASSERT_TRUE(CanCompileAndReflect(
"struct_internal.frag",
402 "There was a compiler error: SkSL does not support array initializers: "
403 "array_initializer_with_constants.frag:6";
405 EXPECT_EXIT(CanCompileAndReflect(
"array_initializer_with_constants.frag",
407 ::testing::ExitedWithCode(1), expected_err);
412 "There was a compiler error: SkSL does not support array initializers: "
413 "array_initializer_with_variables.frag:12";
415 EXPECT_EXIT(CanCompileAndReflect(
"array_initializer_with_variables.frag",
417 ::testing::ExitedWithCode(1), expected_err);
424 ASSERT_FALSE(CanCompileAndReflect(
"array_assignment.frag",
427 const Compiler* compiler = GetCompiler();
428 ASSERT_TRUE(compiler);
432 "\"array_assignment.frag\": \n"
433 "Compiled to invalid SkSL:\n"
434 " // This SkSL shader is autogenerated by spirv-cross.\n"
436 " float4 flutter_FragCoord;\n"
438 " vec4 frag_color;\n"
440 "... (truncated 16 lines)\n"
442 " error: 12: initializers are not permitted on arrays (or structs "
443 "containing arrays)\n"
444 " float more_nums[2] = nums;\n"
449 "\"array_assignment.frag\": \n"
450 "Compiled to invalid SkSL:\n"
451 "// This SkSL shader is autogenerated by spirv-cross.\n"
453 "float4 flutter_FragCoord;\n"
462 " float more_nums[2] = nums;\n"
463 " frag_color = vec4(nums[0], nums[1], 1.0, 1.0);\n"
466 "half4 main(float2 iFragCoord)\n"
468 " flutter_FragCoord = float4(iFragCoord, 0, 0);\n"
470 " return frag_color;\n"
474 "error: 12: initializers are not permitted on arrays (or "
475 "structs containing arrays)\n"
476 " float more_nums[2] = nums;\n"
484 CanCompileAndReflect(
"array_initialization_without_initializer.frag",
490 GTEST_SKIP() <<
"Not supported with SkSL";
493 ASSERT_TRUE(CanCompileAndReflect(
496 std::unique_ptr<fml::FileMapping> json_fd =
497 GetReflectionJson(
"mat2_test.frag");
498 ASSERT_TRUE(json_fd);
499 nlohmann::json shader_json = nlohmann::json::parse(json_fd->GetMapping());
500 nlohmann::json::value_type buffers = shader_json[
"buffers"];
503 ASSERT_GE(buffers.size(), 1u);
504 nlohmann::json::value_type uParams = buffers[0];
505 EXPECT_EQ(uParams[
"name"],
"Params");
507 nlohmann::json::value_type members = uParams[
"type"][
"members"];
510 ASSERT_EQ(members.size(), 1u);
512 nlohmann::json::value_type mat2Member = members[0];
515 EXPECT_EQ(mat2Member[
"type"],
"Mat2");
518 EXPECT_EQ(mat2Member[
"size"], 8u);
522 EXPECT_EQ(mat2Member[
"byte_length"], 32u);
525 EXPECT_EQ(mat2Member[
"array_elements"], 2u);
528 EXPECT_EQ(mat2Member[
"offset"], 0u);
std::string GetVerboseErrorMessages() const
std::shared_ptr< fml::Mapping > GetSPIRVAssembly() const
std::string GetErrorMessages() const
bool operator==(const FlutterPoint &a, const FlutterPoint &b)
std::ostream & operator<<(std::ostream &out, const FlutterPoint &point)
std::unique_ptr< fml::Mapping > OpenFixtureAsMapping(const std::string &fixture_name)
Opens a fixture of the given file name and returns a mapping to its contents.
std::function< ProfileSample(void)> Sampler
Sampler is run during SamplingProfiler::SampleRepeatedly. Each platform should implement its version ...
INSTANTIATE_TEST_SUITE_P(CompilerSuite, CompilerTest, ::testing::Values(TargetPlatform::kOpenGLES, TargetPlatform::kOpenGLDesktop, TargetPlatform::kMetalDesktop, TargetPlatform::kMetalIOS, TargetPlatform::kVulkan), [](const ::testing::TestParamInfo< CompilerTest::ParamType > &info) { return TargetPlatformToString(info.param);})
TEST_P(CompilerTest, CanCompile)
TEST(CompilerTest, Defines)
std::string TargetPlatformToString(TargetPlatform platform)
SourceType SourceTypeFromFileName(const std::filesystem::path &file_name)
bool TargetPlatformIsMetal(TargetPlatform platform)
bool TargetPlatformIsOpenGL(TargetPlatform platform)
bool TargetPlatformIsVulkan(TargetPlatform platform)
TargetPlatform target_platform
SourceLanguage source_language
std::string entry_point_name
TargetPlatform target_platform