Commit e2fc818a by Jonah Ryan-Davis Committed by Angle LUCI CQ

Reland Change to module directory when loading swiftshader ICD.

This is a reland of commit 3b10dda6. Extra changes: Be explicit about calling GetModuleHandleA Do not use the general GetModuleHandle, which may use wide strings Refactored ConcatenatePath and add tests GetModuleDirectory should return the full path, not relative. ANGLE wasn't able to locate the vulkan ICD file because it was searching down an invalid relative path. This can be fixed by ensuring the module directory is always the full path. on some platforms. Original change's description: > When loading vulkan, we can be running from any directory. We need > to change to the module directory to ensure the swiftshader ICD is > loaded properly. For example, in some Chrome releases, libGLESv2.dll > and libvk_swiftshader.dll are in a subdirectory relative to chrome.exe > > Bug: chromium:1198567 > Change-Id: I9e68927e512b239728fb2903d1a04702508a4948 > Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2873452 > Commit-Queue: Jonah Ryan-Davis <jonahr@google.com> > Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org> > Reviewed-by: Jamie Madill <jmadill@chromium.org> Bug: chromium:1198567 Bug: angleproject:5949 Change-Id: I63fbe93f8492b7f23566f8193b1b8fe784a34f71 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2904586Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Jonah Ryan-Davis <jonahr@google.com>
parent 85acc55a
......@@ -107,6 +107,9 @@ config("internal_config") {
if (is_win) {
defines += [ "ANGLE_IS_WIN" ]
if (angle_is_winuwp) {
defines += [ "ANGLE_IS_WINUWP" ]
}
} else if (is_linux || is_chromeos) {
defines += [ "ANGLE_IS_LINUX" ]
}
......
......@@ -93,4 +93,40 @@ bool PrependPathToEnvironmentVar(const char *variableName, const char *path)
}
return SetEnvironmentVar(variableName, newValue);
}
bool IsFullPath(std::string dirName)
{
if (dirName.find(GetRootDirectory()) == 0)
{
return true;
}
return false;
}
std::string ConcatenatePath(std::string first, std::string second)
{
if (first.empty())
{
return second;
}
if (second.empty())
{
return first;
}
if (IsFullPath(second))
{
return first;
}
bool firstRedundantPathSeparator = first.find_last_of(GetPathSeparator()) == first.length() - 1;
bool secondRedundantPathSeparator = second.find(GetPathSeparator()) == 0;
if (firstRedundantPathSeparator && secondRedundantPathSeparator)
{
return first + second.substr(1);
}
else if (firstRedundantPathSeparator || secondRedundantPathSeparator)
{
return first + second;
}
return first + GetPathSeparator() + second;
}
} // namespace angle
......@@ -19,7 +19,7 @@ namespace angle
std::string GetExecutableName();
std::string GetExecutablePath();
std::string GetExecutableDirectory();
std::string GetHelperExecutableDir();
std::string GetModuleDirectory();
const char *GetSharedLibraryExtension();
const char *GetExecutableExtension();
char GetPathSeparator();
......@@ -34,6 +34,9 @@ std::string GetEnvironmentVarOrAndroidProperty(const char *variableName, const c
const char *GetPathSeparatorForEnvironmentVar();
bool PrependPathToEnvironmentVar(const char *variableName, const char *path);
bool IsDirectory(const char *filename);
bool IsFullPath(std::string dirName);
std::string GetRootDirectory();
std::string ConcatenatePath(std::string first, std::string second);
// Get absolute time in seconds. Use this function to get an absolute time with an unknown origin.
double GetCurrentTime();
......
......@@ -56,7 +56,7 @@ const char *GetPathSeparatorForEnvironmentVar()
return ":";
}
std::string GetHelperExecutableDir()
std::string GetModuleDirectory()
{
std::string directory;
static int placeholderSymbol = 0;
......@@ -66,6 +66,12 @@ std::string GetHelperExecutableDir()
std::string moduleName = dlInfo.dli_fname;
directory = moduleName.substr(0, moduleName.find_last_of('/') + 1);
}
// Ensure we return the full path to the module, not the relative path
Optional<std::string> cwd = GetCWD();
if (cwd.valid() && !IsFullPath(directory))
{
directory = ConcatenatePath(cwd.value(), directory);
}
return directory;
}
......@@ -107,7 +113,7 @@ Library *OpenSharedLibrary(const char *libraryName, SearchType searchType)
// On iOS, shared libraries must be loaded from within the app bundle.
directory = GetExecutableDirectory() + "/Frameworks/";
#else
directory = GetHelperExecutableDir();
directory = GetModuleDirectory();
#endif
}
......@@ -154,4 +160,9 @@ char GetPathSeparator()
{
return '/';
}
std::string GetRootDirectory()
{
return "/";
}
} // namespace angle
......@@ -56,4 +56,119 @@ TEST(SystemUtils, Environment)
readback = GetEnvironmentVar(kEnvVarName);
EXPECT_EQ("", readback);
}
#if defined(ANGLE_PLATFORM_POSIX)
TEST(SystemUtils, ConcatenatePathSimple)
{
std::string path1 = "/this/is/path1";
std::string path2 = "this/is/path2";
std::string expected = "/this/is/path1/this/is/path2";
EXPECT_EQ(ConcatenatePath(path1, path2), expected);
}
TEST(SystemUtils, ConcatenatePath1Empty)
{
std::string path1 = "";
std::string path2 = "this/is/path2";
std::string expected = "this/is/path2";
EXPECT_EQ(ConcatenatePath(path1, path2), expected);
}
TEST(SystemUtils, ConcatenatePath2Empty)
{
std::string path1 = "/this/is/path1";
std::string path2 = "";
std::string expected = "/this/is/path1";
EXPECT_EQ(ConcatenatePath(path1, path2), expected);
}
TEST(SystemUtils, ConcatenatePath2FullPath)
{
std::string path1 = "/this/is/path1";
std::string path2 = "/this/is/path2";
std::string expected = "/this/is/path1";
EXPECT_EQ(ConcatenatePath(path1, path2), expected);
}
TEST(SystemUtils, ConcatenatePathRedundantSeparators)
{
std::string path1 = "/this/is/path1/";
std::string path2 = "this/is/path2";
std::string expected = "/this/is/path1/this/is/path2";
EXPECT_EQ(ConcatenatePath(path1, path2), expected);
}
TEST(SystemUtils, IsFullPath)
{
std::string path1 = "/this/is/path1/";
std::string path2 = "this/is/path2";
EXPECT_TRUE(IsFullPath(path1));
EXPECT_FALSE(IsFullPath(path2));
}
#elif defined(ANGLE_PLATFORM_WINDOWS)
TEST(SystemUtils, ConcatenatePathSimple)
{
std::string path1 = "C:\\this\\is\\path1";
std::string path2 = "this\\is\\path2";
std::string expected = "C:\\this\\is\\path1\\this\\is\\path2";
EXPECT_EQ(ConcatenatePath(path1, path2), expected);
}
TEST(SystemUtils, ConcatenatePath1Empty)
{
std::string path1 = "";
std::string path2 = "this\\is\\path2";
std::string expected = "this\\is\\path2";
EXPECT_EQ(ConcatenatePath(path1, path2), expected);
}
TEST(SystemUtils, ConcatenatePath2Empty)
{
std::string path1 = "C:\\this\\is\\path1";
std::string path2 = "";
std::string expected = "C:\\this\\is\\path1";
EXPECT_EQ(ConcatenatePath(path1, path2), expected);
}
TEST(SystemUtils, ConcatenatePath2FullPath)
{
std::string path1 = "C:\\this\\is\\path1";
std::string path2 = "C:\\this\\is\\path2";
std::string expected = "C:\\this\\is\\path1";
EXPECT_EQ(ConcatenatePath(path1, path2), expected);
}
TEST(SystemUtils, ConcatenatePathRedundantSeparators)
{
std::string path1 = "C:\\this\\is\\path1\\";
std::string path2 = "this\\is\\path2";
std::string expected = "C:\\this\\is\\path1\\this\\is\\path2";
EXPECT_EQ(ConcatenatePath(path1, path2), expected);
}
TEST(SystemUtils, ConcatenatePathRedundantSeparators2)
{
std::string path1 = "C:\\this\\is\\path1\\";
std::string path2 = "\\this\\is\\path2";
std::string expected = "C:\\this\\is\\path1\\this\\is\\path2";
EXPECT_EQ(ConcatenatePath(path1, path2), expected);
}
TEST(SystemUtils, ConcatenatePathRedundantSeparators3)
{
std::string path1 = "C:\\this\\is\\path1";
std::string path2 = "\\this\\is\\path2";
std::string expected = "C:\\this\\is\\path1\\this\\is\\path2";
EXPECT_EQ(ConcatenatePath(path1, path2), expected);
}
TEST(SystemUtils, IsFullPath)
{
std::string path1 = "C:\\this\\is\\path1\\";
std::string path2 = "this\\is\\path2";
EXPECT_TRUE(IsFullPath(path1));
EXPECT_FALSE(IsFullPath(path2));
}
#endif
} // anonymous namespace
......@@ -15,21 +15,37 @@
namespace angle
{
std::string GetExecutablePath()
namespace
{
std::string GetPath(HMODULE module)
{
std::array<char, MAX_PATH> executableFileBuf;
DWORD executablePathLen = GetModuleFileNameA(nullptr, executableFileBuf.data(),
DWORD executablePathLen = GetModuleFileNameA(module, executableFileBuf.data(),
static_cast<DWORD>(executableFileBuf.size()));
return (executablePathLen > 0 ? std::string(executableFileBuf.data()) : "");
}
std::string GetExecutableDirectory()
std::string GetDirectory(HMODULE module)
{
std::string executablePath = GetExecutablePath();
std::string executablePath = GetPath(module);
size_t lastPathSepLoc = executablePath.find_last_of("\\/");
return (lastPathSepLoc != std::string::npos) ? executablePath.substr(0, lastPathSepLoc) : "";
}
} // anonymous namespace
std::string GetExecutablePath()
{
return GetPath(nullptr);
}
std::string GetExecutableDirectory()
{
return GetDirectory(nullptr);
}
const char *GetSharedLibraryExtension()
{
return "dll";
......@@ -101,8 +117,25 @@ char GetPathSeparator()
return '\\';
}
std::string GetHelperExecutableDir()
std::string GetModuleDirectory()
{
// GetModuleHandleEx is unavailable on UWP
#if !defined(ANGLE_IS_WINUWP)
static int placeholderSymbol = 0;
HMODULE module = nullptr;
if (GetModuleHandleExA(
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
reinterpret_cast<LPCSTR>(&placeholderSymbol), &module))
{
return GetDirectory(module);
}
#endif
return GetDirectory(nullptr);
}
std::string GetRootDirectory()
{
return "";
return "C:\\";
}
} // namespace angle
......@@ -51,12 +51,9 @@ namespace
!defined(ANGLE_PLATFORM_GGP)
const std::string WrapICDEnvironment(const char *icdEnvironment)
{
# if defined(ANGLE_PLATFORM_APPLE)
// On MacOS the libraries are bundled into the application directory
std::string ret = angle::GetHelperExecutableDir() + icdEnvironment;
// The libraries are bundled into the module directory
std::string ret = ConcatenatePath(angle::GetModuleDirectory(), icdEnvironment);
return ret;
# endif // defined(ANGLE_PLATFORM_APPLE)
return icdEnvironment;
}
constexpr char kLoaderLayersPathEnv[] = "VK_LAYER_PATH";
......@@ -146,9 +143,9 @@ ScopedVkLoaderEnvironment::ScopedVkLoaderEnvironment(bool enableValidationLayers
}
else
{
mPreviousCWD = cwd.value();
std::string exeDir = angle::GetExecutableDirectory();
mChangedCWD = angle::SetCWD(exeDir.c_str());
mPreviousCWD = cwd.value();
std::string moduleDir = angle::GetModuleDirectory();
mChangedCWD = angle::SetCWD(moduleDir.c_str());
if (!mChangedCWD)
{
ERR() << "Error setting CWD for Vulkan layers init.";
......
......@@ -427,9 +427,8 @@ void CLPlatformCL::Initialize(const cl_icd_dispatch &dispatch, bool isIcd)
}
// The absolute path to ANGLE's OpenCL library is needed and it is assumed here that
// it is in the same directory as the module which contains this CL back end.
// TODO(http://anglebug.com/5949) Use GetModuleDirectory when it relands
std::string libPath; // = angle::GetModuleDirectory();
// it is in the same directory as the shared library which contains this CL back end.
std::string libPath = angle::GetModuleDirectory();
if (!libPath.empty() && libPath.back() != angle::GetPathSeparator())
{
libPath += angle::GetPathSeparator();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment