[Impeller] Don't double-convert include path encodings in ImpellerC (#37408)

diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter
index 5cb3aed..0f6405a 100644
--- a/ci/licenses_golden/licenses_flutter
+++ b/ci/licenses_golden/licenses_flutter
@@ -1124,6 +1124,7 @@
 FILE: ../../../flutter/impeller/compiler/spirv_sksl.h
 FILE: ../../../flutter/impeller/compiler/switches.cc
 FILE: ../../../flutter/impeller/compiler/switches.h
+FILE: ../../../flutter/impeller/compiler/switches_unittests.cc
 FILE: ../../../flutter/impeller/compiler/types.cc
 FILE: ../../../flutter/impeller/compiler/types.h
 FILE: ../../../flutter/impeller/compiler/utilities.cc
diff --git a/impeller/compiler/BUILD.gn b/impeller/compiler/BUILD.gn
index 8512408..3098941 100644
--- a/impeller/compiler/BUILD.gn
+++ b/impeller/compiler/BUILD.gn
@@ -120,6 +120,7 @@
     "compiler_test.cc",
     "compiler_test.h",
     "compiler_unittests.cc",
+    "switches_unittests.cc",
   ]
 
   deps = [
diff --git a/impeller/compiler/switches.cc b/impeller/compiler/switches.cc
index 4ca2a27..1e73352 100644
--- a/impeller/compiler/switches.cc
+++ b/impeller/compiler/switches.cc
@@ -127,11 +127,17 @@
 
     // fml::OpenDirectoryReadOnly for Windows doesn't handle relative paths
     // beginning with `../` well, so we build an absolute path.
+
+    // Get the current working directory as a utf8 encoded string.
+    // Note that the `include_dir_path` is already utf8 encoded, and so we
+    // mustn't attempt to double-convert it to utf8 lest multi-byte characters
+    // will become mangled.
+    auto cwd = Utf8FromPath(std::filesystem::current_path());
     auto include_dir_absolute = std::filesystem::absolute(
-        std::filesystem::current_path() / include_dir_path);
+        std::filesystem::path(cwd) / include_dir_path);
 
     auto dir = std::make_shared<fml::UniqueFD>(fml::OpenDirectoryReadOnly(
-        *working_directory, Utf8FromPath(include_dir_absolute).c_str()));
+        *working_directory, include_dir_absolute.string().c_str()));
     if (!dir || !dir->is_valid()) {
       continue;
     }
diff --git a/impeller/compiler/switches_unittests.cc b/impeller/compiler/switches_unittests.cc
new file mode 100644
index 0000000..54ca1e2
--- /dev/null
+++ b/impeller/compiler/switches_unittests.cc
@@ -0,0 +1,36 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "flutter/fml/command_line.h"
+#include "flutter/fml/file.h"
+#include "flutter/testing/testing.h"
+#include "impeller/compiler/switches.h"
+#include "impeller/compiler/utilities.h"
+
+namespace impeller {
+namespace compiler {
+namespace testing {
+
+TEST(SwitchesTest, DoesntMangleUnicodeIncludes) {
+  const char* directory_name = "test_shader_include_�";
+  fml::CreateDirectory(flutter::testing::OpenFixturesDirectory(),
+                       {directory_name}, fml::FilePermission::kRead);
+
+  auto include_path =
+      std::string(flutter::testing::GetFixturesPath()) + "/" + directory_name;
+  auto include_option = "--include=" + include_path;
+
+  const auto cl = fml::CommandLineFromInitializerList(
+      {"impellerc", "--opengl-desktop", "--input=input.vert",
+       "--sl=output.vert", "--spirv=output.spirv", include_option.c_str()});
+  Switches switches(cl);
+  ASSERT_TRUE(switches.AreValid(std::cout));
+  ASSERT_EQ(switches.include_directories.size(), 1u);
+  ASSERT_NE(switches.include_directories[0].dir, nullptr);
+  ASSERT_EQ(switches.include_directories[0].name, include_path);
+}
+
+}  // namespace testing
+}  // namespace compiler
+}  // namespace impeller
diff --git a/impeller/compiler/utilities.h b/impeller/compiler/utilities.h
index 7b05d30..61af436 100644
--- a/impeller/compiler/utilities.h
+++ b/impeller/compiler/utilities.h
@@ -13,6 +13,12 @@
 namespace impeller {
 namespace compiler {
 
+/// @brief  Converts a native format path to a utf8 string.
+///
+///         This utility uses `path::u8string()` to convert native paths to
+///         utf8. If the given path doesn't match the underlying native path
+///         format, and the native path format isn't utf8 (i.e. Windows, which
+///         has utf16 paths), the path will get mangled.
 std::string Utf8FromPath(const std::filesystem::path& path);
 
 std::string InferShaderNameFromPath(std::string_view path);