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 =
83 std::shared_ptr<const fml::Mapping> fixture =
85 "check_gles_unflipped_definition.frag");
128 std::shared_ptr<fml::Mapping> fixture =
144 Compiler compiler(fixture, options, reflector_options);
149 if (!sl || !sl->GetMapping()) {
152 return std::string(
reinterpret_cast<const char*
>(sl->GetMapping()),
159 EXPECT_NE(gl_vert.find(
"uniform float _impeller_y_flip"), std::string::npos)
160 <<
"GLES vertex shader is missing the y-flip uniform declaration:\n"
162 EXPECT_NE(gl_vert.find(
"gl_Position.y *= _impeller_y_flip"),
164 <<
"GLES vertex shader is missing the y-flip epilogue:\n"
168 const std::string gl_frag = compile(
170 EXPECT_EQ(gl_frag.find(
"_impeller_y_flip"), std::string::npos)
171 <<
"GLES fragment shader was unexpectedly injected:\n"
177 EXPECT_EQ(mtl_vert.find(
"_impeller_y_flip"), std::string::npos)
178 <<
"Metal vertex shader was unexpectedly injected:\n"
185 std::shared_ptr<fml::Mapping> fixture =
201 Compiler compiler(fixture, options, reflector_options);
202 ASSERT_TRUE(compiler.
IsValid());
204 ASSERT_TRUE(sl && sl->GetMapping());
205 const std::string gl_vert(
reinterpret_cast<const char*
>(sl->GetMapping()),
208 EXPECT_NE(gl_vert.find(
"void _impeller_user_main("), std::string::npos)
210 EXPECT_NE(gl_vert.find(
"_impeller_user_main();"), std::string::npos)
212 EXPECT_NE(gl_vert.find(
"gl_Position.y *= _impeller_y_flip"),
217 const size_t first_main = gl_vert.find(
"\nvoid main(");
218 ASSERT_NE(first_main, std::string::npos);
219 EXPECT_EQ(gl_vert.find(
"\nvoid main(", first_main + 1), std::string::npos)
232 ASSERT_TRUE(CanCompileAndReflect(
"sample.vert"));
239 ASSERT_TRUE(CanCompileAndReflect(
244 ASSERT_TRUE(CanCompileAndReflect(
"multiple_stages.hlsl",
247 ASSERT_TRUE(CanCompileAndReflect(
"multiple_stages.hlsl",
265 ASSERT_FALSE(CanCompileAndReflect(
"struct_def_bug.vert"));
270 GTEST_SKIP() <<
"Only GL targets lower uniform blocks to flat structs.";
276 auto sl_source = GetCompiler()->GetSLShaderSource();
277 ASSERT_NE(sl_source,
nullptr);
278 const std::string source(
279 reinterpret_cast<const char*
>(sl_source->GetMapping()),
280 sl_source->GetSize());
281 EXPECT_EQ(source.find(
"uParams."), std::string::npos) << source;
282 EXPECT_NE(source.find(
"_Params."), std::string::npos) << source;
293 auto get_binding = [&](
const char* fixture) -> uint32_t {
294 auto json_fd = GetReflectionJson(fixture);
295 nlohmann::json shader_json = nlohmann::json::parse(json_fd->GetMapping());
296 return shader_json[
"buffers"][0][
"binding"].get<uint32_t>();
299 auto vert_uniform_binding = get_binding(
"sample.vert");
300 auto frag_uniform_binding = get_binding(
"sample.frag");
302 ASSERT_GT(frag_uniform_binding, vert_uniform_binding);
313 static UniformInfo fromJson(
const nlohmann::json& json) {
315 .uniform_name = json[
"name"].get<std::string>(),
316 .
location = json[
"location"].get<uint32_t>(),
317 .type_name = json[
"type"][
"type_name"].get<std::string>(),
318 .
columns = json[
"type"][
"columns"].get<uint32_t>(),
319 .vec_size = json[
"type"][
"vec_size"].get<uint32_t>(),
323 static UniformInfo
Sampler(
const std::string&
name, uint32_t location) {
325 .uniform_name =
name,
327 .type_name =
"ShaderType::kSampledImage",
332 static UniformInfo Float(
const std::string&
name, uint32_t location) {
333 return FloatInfo(
name, location, 1u, 1u);
335 static UniformInfo Vec2(
const std::string&
name, uint32_t location) {
336 return FloatInfo(
name, location, 1u, 2u);
338 static UniformInfo Vec3(
const std::string&
name, uint32_t location) {
339 return FloatInfo(
name, location, 1u, 3u);
341 static UniformInfo Vec4(
const std::string&
name, uint32_t location) {
342 return FloatInfo(
name, location, 1u, 4u);
344 static UniformInfo Mat4(
const std::string&
name, uint32_t location) {
345 return FloatInfo(
name, location, 4u, 4u);
348 constexpr bool operator==(
const UniformInfo& other)
const {
349 return (uniform_name == other.uniform_name &&
350 location == other.location &&
351 type_name == other.type_name &&
352 columns == other.columns &&
353 vec_size == other.vec_size);
357 static UniformInfo FloatInfo(
const std::string&
name,
362 .uniform_name =
name,
364 .type_name =
"ShaderType::kFloat",
371inline std::ostream&
operator<<(std::ostream& out,
const UniformInfo& info) {
372 out <<
"UniformInfo {" << std::endl
373 <<
" uniform_name: " << info.uniform_name << std::endl
374 <<
" location: " << info.location << std::endl
375 <<
" type_name: " << info.type_name << std::endl
376 <<
" columns: " << info.columns << std::endl
377 <<
" vec_size: " << info.vec_size << std::endl
387 GTEST_SKIP() <<
"Not supported with Vulkan";
390 ASSERT_TRUE(CanCompileAndReflect(
"sample_with_uniforms.frag",
394 auto json_fd = GetReflectionJson(
"sample_with_uniforms.frag");
395 ASSERT_TRUE(json_fd);
396 nlohmann::json shader_json = nlohmann::json::parse(json_fd->GetMapping());
397 auto sampler_list = shader_json[
"sampled_images"];
398 auto float_list = shader_json[
"uniforms"];
399 ASSERT_EQ(sampler_list.size(), 2u);
400 ASSERT_EQ(float_list.size(), 6u);
404 std::array expected_infos = {
405 UniformInfo::Sampler(
"uFirstSampler", 1u),
406 UniformInfo::Sampler(
"uSampler", 7u),
409 ASSERT_EQ(sampler_list.size(), expected_infos.size());
410 for (
size_t i = 0;
i < expected_infos.size();
i++) {
411 EXPECT_EQ(UniformInfo::fromJson(sampler_list[
i]), expected_infos[
i])
418 std::array expected_infos = {
419 UniformInfo::Float(
"uFirstFloat", 0u),
420 UniformInfo::Float(
"uFloat", 2u),
421 UniformInfo::Vec2(
"uVec2", 3u),
422 UniformInfo::Vec3(
"uVec3", 4u),
423 UniformInfo::Vec4(
"uVec4", 5u),
424 UniformInfo::Mat4(
"uMat4", 6u),
427 ASSERT_EQ(float_list.size(), expected_infos.size());
428 for (
size_t i = 0;
i < expected_infos.size();
i++) {
429 EXPECT_EQ(UniformInfo::fromJson(float_list[
i]), expected_infos[
i])
439 GTEST_SKIP() <<
"Not supported with Vulkan";
442 ASSERT_TRUE(CanCompileAndReflect(
"sample_with_positioned_uniforms.frag",
446 auto json_fd = GetReflectionJson(
"sample_with_positioned_uniforms.frag");
447 ASSERT_TRUE(json_fd);
448 nlohmann::json shader_json = nlohmann::json::parse(json_fd->GetMapping());
449 auto sampler_list = shader_json[
"sampled_images"];
450 auto float_list = shader_json[
"uniforms"];
451 ASSERT_EQ(sampler_list.size(), 3u);
452 ASSERT_EQ(float_list.size(), 7u);
456 std::array expected_infos = {
457 UniformInfo::Sampler(
"uSamplerNotPositioned1", 1u),
458 UniformInfo::Sampler(
"uSampler", 0u),
459 UniformInfo::Sampler(
"uSamplerNotPositioned2", 3u),
462 ASSERT_EQ(sampler_list.size(), expected_infos.size());
463 for (
size_t i = 0;
i < expected_infos.size();
i++) {
464 EXPECT_EQ(UniformInfo::fromJson(sampler_list[
i]), expected_infos[
i])
471 std::array expected_infos = {
472 UniformInfo::Float(
"uFloatNotPositioned1", 0u),
473 UniformInfo::Float(
"uFloat", 6u),
474 UniformInfo::Vec2(
"uVec2", 5u),
475 UniformInfo::Vec3(
"uVec3", 3u),
476 UniformInfo::Vec4(
"uVec4", 2u),
477 UniformInfo::Mat4(
"uMat4", 1u),
478 UniformInfo::Float(
"uFloatNotPositioned2", 2u),
481 ASSERT_EQ(float_list.size(), expected_infos.size());
482 for (
size_t i = 0;
i < expected_infos.size();
i++) {
483 EXPECT_EQ(UniformInfo::fromJson(float_list[
i]), expected_infos[
i])
491 GTEST_SKIP() <<
"Not supported with SkSL";
493 ASSERT_TRUE(CanCompileAndReflect(
"sample_with_binding.vert",
497 struct binding_and_set {
502 auto get_binding = [&](
const char* fixture) -> binding_and_set {
503 auto json_fd = GetReflectionJson(fixture);
504 nlohmann::json shader_json = nlohmann::json::parse(json_fd->GetMapping());
505 uint32_t binding = shader_json[
"buffers"][0][
"binding"].get<uint32_t>();
506 uint32_t set = shader_json[
"buffers"][0][
"set"].get<uint32_t>();
507 return {binding, set};
510 auto vert_uniform_binding = get_binding(
"sample_with_binding.vert");
511 auto frag_uniform_binding = get_binding(
"sample.frag");
513 ASSERT_EQ(frag_uniform_binding.set, 0u);
514 ASSERT_EQ(vert_uniform_binding.set, 3u);
515 ASSERT_EQ(vert_uniform_binding.binding, 17u);
522 auto shader = GetShaderFile(
"texture_lookup.frag", GetParam());
523 std::string_view shader_mapping(
524 reinterpret_cast<const char*
>(shader->GetMapping()), shader->GetSize());
526 constexpr std::string_view expected =
527 "textureA.eval(textureA_size * ( vec2(1.0) + flutter_FragCoord.xy));";
529 EXPECT_NE(shader_mapping.find(expected), std::string::npos);
533 ASSERT_TRUE(CanCompileAndReflect(
"struct_internal.frag",
539 "There was a compiler error: SkSL does not support array initializers: "
540 "array_initializer_with_constants.frag:6";
542 EXPECT_EXIT(CanCompileAndReflect(
"array_initializer_with_constants.frag",
544 ::testing::ExitedWithCode(1), expected_err);
549 "There was a compiler error: SkSL does not support array initializers: "
550 "array_initializer_with_variables.frag:12";
552 EXPECT_EXIT(CanCompileAndReflect(
"array_initializer_with_variables.frag",
554 ::testing::ExitedWithCode(1), expected_err);
561 ASSERT_FALSE(CanCompileAndReflect(
"array_assignment.frag",
564 const Compiler* compiler = GetCompiler();
565 ASSERT_TRUE(compiler);
569 "\"array_assignment.frag\": \n"
570 "Compiled to invalid SkSL:\n"
571 " // This SkSL shader is autogenerated by spirv-cross.\n"
573 " float4 flutter_FragCoord;\n"
575 " vec4 frag_color;\n"
577 "... (truncated 16 lines)\n"
579 " error: 12: initializers are not permitted on arrays (or structs "
580 "containing arrays)\n"
581 " float more_nums[2] = nums;\n"
586 "\"array_assignment.frag\": \n"
587 "Compiled to invalid SkSL:\n"
588 "// This SkSL shader is autogenerated by spirv-cross.\n"
590 "float4 flutter_FragCoord;\n"
599 " float more_nums[2] = nums;\n"
600 " frag_color = vec4(nums[0], nums[1], 1.0, 1.0);\n"
603 "half4 main(float2 iFragCoord)\n"
605 " flutter_FragCoord = float4(iFragCoord, 0, 0);\n"
607 " return frag_color;\n"
611 "error: 12: initializers are not permitted on arrays (or "
612 "structs containing arrays)\n"
613 " float more_nums[2] = nums;\n"
621 CanCompileAndReflect(
"array_initialization_without_initializer.frag",
627 GTEST_SKIP() <<
"Not supported with SkSL";
630 ASSERT_TRUE(CanCompileAndReflect(
633 std::unique_ptr<fml::FileMapping> json_fd =
634 GetReflectionJson(
"mat2_test.frag");
635 ASSERT_TRUE(json_fd);
636 nlohmann::json shader_json = nlohmann::json::parse(json_fd->GetMapping());
637 nlohmann::json::value_type buffers = shader_json[
"buffers"];
640 ASSERT_GE(buffers.size(), 1u);
641 nlohmann::json::value_type uParams = buffers[0];
642 EXPECT_EQ(uParams[
"name"],
"Params");
644 nlohmann::json::value_type members = uParams[
"type"][
"members"];
647 ASSERT_EQ(members.size(), 1u);
649 nlohmann::json::value_type mat2Member = members[0];
652 EXPECT_EQ(mat2Member[
"type"],
"Mat2");
655 EXPECT_EQ(mat2Member[
"size"], 8u);
659 EXPECT_EQ(mat2Member[
"byte_length"], 32u);
662 EXPECT_EQ(mat2Member[
"array_elements"], 2u);
665 EXPECT_EQ(mat2Member[
"offset"], 0u);
std::string GetVerboseErrorMessages() const
std::shared_ptr< fml::Mapping > GetSPIRVAssembly() const
std::shared_ptr< fml::Mapping > GetSLShaderSource() const
std::string GetErrorMessages() const
bool operator==(const FlutterPoint &a, const FlutterPoint &b)
std::ostream & operator<<(std::ostream &out, const FlutterPoint &point)
#define FML_CHECK(condition)
fml::UniqueFD OpenFixturesDirectory()
Opens the fixtures directory for the unit-test harness.
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 TargetPlatformIsOpenGL(TargetPlatform platform)
bool TargetPlatformIsVulkan(TargetPlatform platform)
impeller::ShaderType type
TargetPlatform target_platform
std::string header_file_name
SourceLanguage source_language
std::string entry_point_name
TargetPlatform target_platform
std::shared_ptr< fml::UniqueFD > working_directory