diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index b32f820ed1985..ef718a216eb33 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -565,6 +565,9 @@ FILE: ../../../flutter/impeller/fixtures/impeller.vert FILE: ../../../flutter/impeller/fixtures/instanced_draw.frag FILE: ../../../flutter/impeller/fixtures/instanced_draw.vert FILE: ../../../flutter/impeller/fixtures/kalimba.jpg +FILE: ../../../flutter/impeller/fixtures/sample.comp +FILE: ../../../flutter/impeller/fixtures/sample.tesc +FILE: ../../../flutter/impeller/fixtures/sample.tese FILE: ../../../flutter/impeller/fixtures/sample.vert FILE: ../../../flutter/impeller/fixtures/struct_def_bug.vert FILE: ../../../flutter/impeller/fixtures/table_mountain_nx.png diff --git a/impeller/compiler/compiler.cc b/impeller/compiler/compiler.cc index 5adb4dc42ff82..1d2b14e9e6531 100644 --- a/impeller/compiler/compiler.cc +++ b/impeller/compiler/compiler.cc @@ -204,7 +204,7 @@ Compiler::Compiler(const fml::Mapping& source_mapping, return; } - // MSL Generation. + // SL Generation. spirv_cross::Parser parser(spv_result_->cbegin(), spv_result_->cend() - spv_result_->cbegin()); // The parser and compiler must be run separately because the parser contains @@ -225,7 +225,7 @@ Compiler::Compiler(const fml::Mapping& source_mapping, std::make_shared(sl_compiler.GetCompiler()->compile()); if (!sl_string_) { - COMPILER_ERROR << "Could not generate MSL from SPIRV"; + COMPILER_ERROR << "Could not generate SL from SPIRV"; return; } diff --git a/impeller/compiler/compiler_test.cc b/impeller/compiler/compiler_test.cc index b1d7f9b7f1b46..62d63a2b61334 100644 --- a/impeller/compiler/compiler_test.cc +++ b/impeller/compiler/compiler_test.cc @@ -146,14 +146,14 @@ bool CompilerTest::CanCompileAndReflect(const char* fixture_name) const { if (!fml::WriteAtomically(intermediates_directory_, ReflectionCCName(fixture_name).c_str(), - *reflection_header)) { + *reflection_source)) { VALIDATION_LOG << "Could not write reflection CC intermediates."; return false; } if (!fml::WriteAtomically(intermediates_directory_, ReflectionJSONName(fixture_name).c_str(), - *reflection_header)) { + *reflection_json)) { VALIDATION_LOG << "Could not write reflection json intermediates."; return false; } diff --git a/impeller/compiler/compiler_unittests.cc b/impeller/compiler/compiler_unittests.cc index 5ac7495b09836..9f2bade70d9d1 100644 --- a/impeller/compiler/compiler_unittests.cc +++ b/impeller/compiler/compiler_unittests.cc @@ -16,6 +16,11 @@ namespace testing { TEST(CompilerTest, ShaderKindMatchingIsSuccessful) { ASSERT_EQ(SourceTypeFromFileName("hello.vert"), SourceType::kVertexShader); ASSERT_EQ(SourceTypeFromFileName("hello.frag"), SourceType::kFragmentShader); + ASSERT_EQ(SourceTypeFromFileName("hello.tesc"), + SourceType::kTessellationControlShader); + ASSERT_EQ(SourceTypeFromFileName("hello.tese"), + SourceType::kTessellationEvaluationShader); + ASSERT_EQ(SourceTypeFromFileName("hello.comp"), SourceType::kComputeShader); ASSERT_EQ(SourceTypeFromFileName("hello.msl"), SourceType::kUnknown); ASSERT_EQ(SourceTypeFromFileName("hello.glsl"), SourceType::kUnknown); } @@ -24,6 +29,21 @@ TEST_P(CompilerTest, CanCompile) { ASSERT_TRUE(CanCompileAndReflect("sample.vert")); } +TEST_P(CompilerTest, CanCompileTessellationControlShader) { + ASSERT_TRUE(CanCompileAndReflect("sample.tesc")); +} + +TEST_P(CompilerTest, CanCompileTessellationEvaluationShader) { + ASSERT_TRUE(CanCompileAndReflect("sample.tese")); +} + +TEST_P(CompilerTest, CanCompileComputeShader) { + if (!TargetPlatformIsMetal(GetParam())) { + GTEST_SKIP_("Only enabled on Metal backends till ES 3.2 support is added."); + } + ASSERT_TRUE(CanCompileAndReflect("sample.comp")); +} + TEST_P(CompilerTest, MustFailDueToMultipleLocationPerStructMember) { if (GetParam() == TargetPlatform::kFlutterSPIRV) { // This is a failure of reflection which this target doesn't perform. diff --git a/impeller/compiler/reflector.cc b/impeller/compiler/reflector.cc index fb7a8ac391fc5..85b66408b5f70 100644 --- a/impeller/compiler/reflector.cc +++ b/impeller/compiler/reflector.cc @@ -71,6 +71,12 @@ static std::string ExecutionModelToString(spv::ExecutionModel model) { return "vertex"; case spv::ExecutionModel::ExecutionModelFragment: return "fragment"; + case spv::ExecutionModel::ExecutionModelTessellationControl: + return "tessellation_control"; + case spv::ExecutionModel::ExecutionModelTessellationEvaluation: + return "tessellation_evaluation"; + case spv::ExecutionModel::ExecutionModelGLCompute: + return "compute"; default: return "unsupported"; } @@ -85,6 +91,18 @@ static std::string StringToShaderStage(std::string str) { return "ShaderStage::kFragment"; } + if (str == "tessellation_control") { + return "ShaderStage::kTessellationControl"; + } + + if (str == "tessellation_evaluation") { + return "ShaderStage::kTessellationEvaluation"; + } + + if (str == "compute") { + return "ShaderStage::kCompute"; + } + return "ShaderStage::kUnknown"; } diff --git a/impeller/compiler/types.cc b/impeller/compiler/types.cc index 3cc5130a2fb45..f13035670c326 100644 --- a/impeller/compiler/types.cc +++ b/impeller/compiler/types.cc @@ -34,6 +34,18 @@ SourceType SourceTypeFromFileName(const std::string& file_name) { return SourceType::kFragmentShader; } + if (StringEndWith(file_name, ".tesc")) { + return SourceType::kTessellationControlShader; + } + + if (StringEndWith(file_name, ".tese")) { + return SourceType::kTessellationEvaluationShader; + } + + if (StringEndWith(file_name, ".comp")) { + return SourceType::kComputeShader; + } + return SourceType::kUnknown; } @@ -70,6 +82,15 @@ std::string EntryPointFunctionNameFromSourceName(const std::string& file_name, case SourceType::kFragmentShader: stream << "fragment"; break; + case SourceType::kTessellationControlShader: + stream << "tess_control"; + break; + case SourceType::kTessellationEvaluationShader: + stream << "tess_eval"; + break; + case SourceType::kComputeShader: + stream << "compute"; + break; } stream << "_main"; return stream.str(); @@ -134,6 +155,12 @@ shaderc_shader_kind ToShaderCShaderKind(SourceType type) { return shaderc_shader_kind::shaderc_vertex_shader; case SourceType::kFragmentShader: return shaderc_shader_kind::shaderc_fragment_shader; + case SourceType::kTessellationControlShader: + return shaderc_shader_kind::shaderc_tess_control_shader; + case SourceType::kTessellationEvaluationShader: + return shaderc_shader_kind::shaderc_tess_evaluation_shader; + case SourceType::kComputeShader: + return shaderc_shader_kind::shaderc_compute_shader; case SourceType::kUnknown: break; } @@ -146,6 +173,12 @@ spv::ExecutionModel ToExecutionModel(SourceType type) { return spv::ExecutionModel::ExecutionModelVertex; case SourceType::kFragmentShader: return spv::ExecutionModel::ExecutionModelFragment; + case SourceType::kTessellationControlShader: + return spv::ExecutionModel::ExecutionModelTessellationControl; + case SourceType::kTessellationEvaluationShader: + return spv::ExecutionModel::ExecutionModelTessellationEvaluation; + case SourceType::kComputeShader: + return spv::ExecutionModel::ExecutionModelGLCompute; case SourceType::kUnknown: break; } @@ -176,6 +209,12 @@ std::string SourceTypeToString(SourceType type) { return "vert"; case SourceType::kFragmentShader: return "frag"; + case SourceType::kTessellationControlShader: + return "tesc"; + case SourceType::kTessellationEvaluationShader: + return "tese"; + case SourceType::kComputeShader: + return "comp"; } FML_UNREACHABLE(); } @@ -204,5 +243,31 @@ std::string ToUtf8(const std::string& string) { return string; } +bool TargetPlatformIsOpenGL(TargetPlatform platform) { + switch (platform) { + case TargetPlatform::kOpenGLES: + case TargetPlatform::kOpenGLDesktop: + return true; + case TargetPlatform::kMetalDesktop: + case TargetPlatform::kMetalIOS: + case TargetPlatform::kUnknown: + case TargetPlatform::kFlutterSPIRV: + return false; + } +} + +bool TargetPlatformIsMetal(TargetPlatform platform) { + switch (platform) { + case TargetPlatform::kMetalDesktop: + case TargetPlatform::kMetalIOS: + return true; + case TargetPlatform::kUnknown: + case TargetPlatform::kFlutterSPIRV: + case TargetPlatform::kOpenGLES: + case TargetPlatform::kOpenGLDesktop: + return false; + } +} + } // namespace compiler } // namespace impeller diff --git a/impeller/compiler/types.h b/impeller/compiler/types.h index e714463810f78..b709546644fdf 100644 --- a/impeller/compiler/types.h +++ b/impeller/compiler/types.h @@ -20,6 +20,9 @@ enum class SourceType { kUnknown, kVertexShader, kFragmentShader, + kTessellationControlShader, + kTessellationEvaluationShader, + kComputeShader, }; enum class TargetPlatform { @@ -31,6 +34,10 @@ enum class TargetPlatform { kOpenGLDesktop, }; +bool TargetPlatformIsMetal(TargetPlatform platform); + +bool TargetPlatformIsOpenGL(TargetPlatform platform); + SourceType SourceTypeFromFileName(const std::string& file_name); std::string SourceTypeToString(SourceType type); diff --git a/impeller/fixtures/BUILD.gn b/impeller/fixtures/BUILD.gn index b2a56601edabd..3e7da09fd9109 100644 --- a/impeller/fixtures/BUILD.gn +++ b/impeller/fixtures/BUILD.gn @@ -30,6 +30,9 @@ test_fixtures("file_fixtures") { "embarcadero.jpg", "kalimba.jpg", "sample.vert", + "sample.tesc", + "sample.tese", + "sample.comp", "struct_def_bug.vert", "table_mountain_nx.png", "table_mountain_ny.png", diff --git a/impeller/fixtures/sample.comp b/impeller/fixtures/sample.comp new file mode 100644 index 0000000000000..4e76c29968958 --- /dev/null +++ b/impeller/fixtures/sample.comp @@ -0,0 +1,5 @@ +layout (local_size_x = 16, local_size_y = 16) in; + +void main(void) { + // Do nothing. +} diff --git a/impeller/fixtures/sample.tesc b/impeller/fixtures/sample.tesc new file mode 100644 index 0000000000000..6eb4156e21966 --- /dev/null +++ b/impeller/fixtures/sample.tesc @@ -0,0 +1,5 @@ +layout(vertices = 4) out; + +void main() { + gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; +} diff --git a/impeller/fixtures/sample.tese b/impeller/fixtures/sample.tese new file mode 100644 index 0000000000000..b1d3108fd2c3a --- /dev/null +++ b/impeller/fixtures/sample.tese @@ -0,0 +1,14 @@ +layout (quads, equal_spacing, ccw) in; + +void main() { + float u = gl_TessCoord.x; + float omu = 1 - u; + float v = gl_TessCoord.y; + float omv = 1 - v; + + gl_Position = + omu * omv * gl_in[0].gl_Position + + u * omv * gl_in[1].gl_Position + + u * v * gl_in[2].gl_Position + + omu * v * gl_in[3].gl_Position; +} diff --git a/impeller/renderer/backend/gles/pipeline_library_gles.cc b/impeller/renderer/backend/gles/pipeline_library_gles.cc index 5147595d93ea9..a06bf7e1703c4 100644 --- a/impeller/renderer/backend/gles/pipeline_library_gles.cc +++ b/impeller/renderer/backend/gles/pipeline_library_gles.cc @@ -48,6 +48,15 @@ static void LogShaderCompilationFailure(const ProcTableGLES& gl, case ShaderStage::kFragment: stream << "fragment"; break; + case ShaderStage::kTessellationControl: + stream << "tessellation control"; + break; + case ShaderStage::kTessellationEvaluation: + stream << "tessellation evaluation"; + break; + case ShaderStage::kCompute: + stream << "compute"; + break; } stream << " shader for '" << name << "' with error:" << std::endl; stream << GetShaderInfoLog(gl, shader) << std::endl; diff --git a/impeller/renderer/backend/gles/shader_library_gles.cc b/impeller/renderer/backend/gles/shader_library_gles.cc index 99345f14b0196..8af6e62d98558 100644 --- a/impeller/renderer/backend/gles/shader_library_gles.cc +++ b/impeller/renderer/backend/gles/shader_library_gles.cc @@ -37,6 +37,15 @@ static std::string GLESShaderNameToShaderKeyName(const std::string& name, case ShaderStage::kFragment: stream << "_fragment_"; break; + case ShaderStage::kTessellationControl: + stream << "_tessellation_control_"; + break; + case ShaderStage::kTessellationEvaluation: + stream << "_tessellation_evaluation_"; + break; + case ShaderStage::kCompute: + stream << "_compute_"; + break; } stream << "main"; return stream.str(); diff --git a/impeller/renderer/command.cc b/impeller/renderer/command.cc index 894e196f51910..c8904ef5fedd4 100644 --- a/impeller/renderer/command.cc +++ b/impeller/renderer/command.cc @@ -48,6 +48,9 @@ bool Command::BindResource(ShaderStage stage, case ShaderStage::kFragment: fragment_bindings.buffers[slot.binding] = {&metadata, view}; return true; + case ShaderStage::kTessellationControl: + case ShaderStage::kTessellationEvaluation: + case ShaderStage::kCompute: case ShaderStage::kUnknown: return false; } @@ -74,6 +77,9 @@ bool Command::BindResource(ShaderStage stage, case ShaderStage::kFragment: fragment_bindings.textures[slot.texture_index] = {&metadata, texture}; return true; + case ShaderStage::kTessellationControl: + case ShaderStage::kTessellationEvaluation: + case ShaderStage::kCompute: case ShaderStage::kUnknown: return false; } @@ -101,6 +107,9 @@ bool Command::BindResource(ShaderStage stage, fragment_bindings.samplers[slot.sampler_index] = {&metadata, sampler}; return true; case ShaderStage::kUnknown: + case ShaderStage::kTessellationControl: + case ShaderStage::kTessellationEvaluation: + case ShaderStage::kCompute: return false; } diff --git a/impeller/renderer/shader_types.h b/impeller/renderer/shader_types.h index c702157731fc4..7750032b030e9 100644 --- a/impeller/renderer/shader_types.h +++ b/impeller/renderer/shader_types.h @@ -17,6 +17,9 @@ enum class ShaderStage { kUnknown, kVertex, kFragment, + kTessellationControl, + kTessellationEvaluation, + kCompute, }; enum class ShaderType {