Commit 7107a0f3 by John Plate Committed by Commit Bot

CL: Load OpenCL without search path modification

Make it possible to load libGLESv2 and OpenCL_ANGLE without adding ANGLE's binary directory to the search path. Bug: angleproject:5904 Change-Id: Ie810466b39e1101e4da5b9fd199d26683b129281 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2897250 Commit-Queue: John Plate <jplate@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCody Northrop <cnorthrop@google.com>
parent c2fd3388
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "anglebase/no_destructor.h" #include "anglebase/no_destructor.h"
#include "common/angle_version.h" #include "common/angle_version.h"
#include "common/system_utils.h"
extern "C" { extern "C" {
#include "icd.h" #include "icd.h"
...@@ -391,16 +392,27 @@ void CLPlatformCL::Initialize(const cl_icd_dispatch &dispatch, bool isIcd) ...@@ -391,16 +392,27 @@ void CLPlatformCL::Initialize(const cl_icd_dispatch &dispatch, bool isIcd)
return; return;
} }
// The absolute path to ANGLE's OpenCL library is needed and it is assumed here that
// 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();
}
libPath += ANGLE_OPENCL_LIB_NAME;
libPath += '.';
libPath += angle::GetSharedLibraryExtension();
// Our OpenCL entry points are not reentrant, so we have to prevent khrIcdInitialize() // Our OpenCL entry points are not reentrant, so we have to prevent khrIcdInitialize()
// from querying ANGLE's OpenCL library. We store a dummy entry with the library in the // from querying ANGLE's OpenCL library. We store a dummy entry with the library in the
// khrIcdVendors list, because the ICD Loader skips the libraries which are already in // khrIcdVendors list, because the ICD Loader skips the libraries which are already in
// the list as it assumes they were already enumerated. // the list as it assumes they were already enumerated.
static angle::base::NoDestructor<KHRicdVendor> sVendorAngle({}); static angle::base::NoDestructor<KHRicdVendor> sVendorAngle({});
sVendorAngle->library = khrIcdOsLibraryLoad(ANGLE_OPENCL_LIB_NAME); sVendorAngle->library = khrIcdOsLibraryLoad(libPath.c_str());
khrIcdVendors = sVendorAngle.get(); khrIcdVendors = sVendorAngle.get();
if (khrIcdVendors->library == nullptr) if (khrIcdVendors->library == nullptr)
{ {
WARN() << "Unable to load library \"" ANGLE_OPENCL_LIB_NAME "\""; WARN() << "Unable to load library \"" << libPath << "\"";
return; return;
} }
......
...@@ -9,17 +9,25 @@ import("../../gni/angle.gni") ...@@ -9,17 +9,25 @@ import("../../gni/angle.gni")
assert(angle_enable_cl) assert(angle_enable_cl)
cl_library_name = "OpenCL_ANGLE" cl_library_name = "OpenCL_ANGLE"
if (is_win || is_linux) {
glesv2_path =
rebase_path(get_label_info("$angle_root:libGLESv2", "root_out_dir"))
}
config("opencl_library_name") { config("opencl_library_name") {
if (is_win) { if (is_win) {
defines = [ "ANGLE_OPENCL_LIB_NAME=\"" + cl_library_name + "\"" ] defines = [ "ANGLE_OPENCL_LIB_NAME=\"" + cl_library_name + "\"" ]
} else { } else {
defines = [ "ANGLE_OPENCL_LIB_NAME=\"lib" + cl_library_name + ".so\"" ] defines = [ "ANGLE_OPENCL_LIB_NAME=\"lib" + cl_library_name + "\"" ]
} }
} }
angle_shared_library(cl_library_name) { angle_shared_library(cl_library_name) {
defines = [ "LIBCL_IMPLEMENTATION" ] defines = [ "LIBCL_IMPLEMENTATION" ]
if (is_win) {
defines += [ "ANGLE_GLESV2_LIBRARY_PATH=\"" +
string_replace(glesv2_path, "/", "\\\\") + "\"" ]
}
sources = [ sources = [
"dispatch.cpp", "dispatch.cpp",
...@@ -39,8 +47,11 @@ angle_shared_library(cl_library_name) { ...@@ -39,8 +47,11 @@ angle_shared_library(cl_library_name) {
if (is_linux) { if (is_linux) {
inputs = [ "libOpenCL_autogen.map" ] inputs = [ "libOpenCL_autogen.map" ]
ldflags = [ "-Wl,--version-script=" + ldflags = [
rebase_path("libOpenCL_autogen.map", root_build_dir) ] "-Wl,--version-script=" +
rebase_path("libOpenCL_autogen.map", root_build_dir),
"-Wl,-rpath=" + glesv2_path,
]
} }
} }
......
...@@ -8,11 +8,15 @@ ...@@ -8,11 +8,15 @@
#include "libOpenCL/dispatch.h" #include "libOpenCL/dispatch.h"
#include "anglebase/no_destructor.h" #include "anglebase/no_destructor.h"
#include "common/debug.h"
#include "common/system_utils.h" #include "common/system_utils.h"
#include <iostream>
#include <memory> #include <memory>
#ifdef _WIN32
# include <windows.h>
#endif
namespace cl namespace cl
{ {
...@@ -27,30 +31,69 @@ std::unique_ptr<angle::Library> &EntryPointsLib() ...@@ -27,30 +31,69 @@ std::unique_ptr<angle::Library> &EntryPointsLib()
IcdDispatch CreateDispatch() IcdDispatch CreateDispatch()
{ {
IcdDispatch dispatch; const cl_icd_dispatch *clIcdDispatch = nullptr;
const char *error = nullptr;
// Try to find ANGLE's GLESv2 library in the consistent way, which might fail
// if the current library or a link to it is not in ANGLE's binary directory
EntryPointsLib().reset( EntryPointsLib().reset(
angle::OpenSharedLibrary(ANGLE_GLESV2_LIBRARY_NAME, angle::SearchType::ApplicationDir)); angle::OpenSharedLibrary(ANGLE_GLESV2_LIBRARY_NAME, angle::SearchType::ApplicationDir));
if (EntryPointsLib()) if (EntryPointsLib() && EntryPointsLib()->getNative() != nullptr)
{ {
auto clIcdDispatch = reinterpret_cast<const cl_icd_dispatch *>( EntryPointsLib()->getAs("gCLIcdDispatchTable", &clIcdDispatch);
EntryPointsLib()->getSymbol("gCLIcdDispatchTable")); if (clIcdDispatch == nullptr)
if (clIcdDispatch != nullptr)
{
static_cast<cl_icd_dispatch &>(dispatch) = *clIcdDispatch;
dispatch.clIcdGetPlatformIDsKHR = reinterpret_cast<clIcdGetPlatformIDsKHR_fn>(
clIcdDispatch->clGetExtensionFunctionAddress("clIcdGetPlatformIDsKHR"));
}
else
{ {
std::cerr << "Error loading CL dispatch table." << std::endl; INFO() << "Found system's instead of ANGLE's GLESv2 library";
} }
} }
else else
{ {
std::cerr << "Error opening GLESv2 library." << std::endl; error = "Not able to find GLESv2 library";
}
// If not found try to find ANGLE's GLESv2 library in build path
if (clIcdDispatch == nullptr)
{
#ifdef _WIN32
// On Windows the build path 'ANGLE_GLESV2_LIBRARY_PATH' is provided by the build system
const char path[] = ANGLE_GLESV2_LIBRARY_PATH "\\" ANGLE_GLESV2_LIBRARY_NAME ".dll";
// This function allows to load further dependent libraries from the same directory
HMODULE handle = LoadLibraryExA(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
if (handle != nullptr)
{
clIcdDispatch = reinterpret_cast<const cl_icd_dispatch *>(
GetProcAddress(handle, "gCLIcdDispatchTable"));
if (clIcdDispatch == nullptr)
{
error = "Error loading CL dispatch table.";
}
}
#else
// On posix-compatible systems this will also search in the rpath, which is the build path
EntryPointsLib().reset(
angle::OpenSharedLibrary(ANGLE_GLESV2_LIBRARY_NAME, angle::SearchType::SystemDir));
if (EntryPointsLib() && EntryPointsLib()->getNative() != nullptr)
{
EntryPointsLib()->getAs("gCLIcdDispatchTable", &clIcdDispatch);
if (clIcdDispatch == nullptr)
{
INFO() << "Found system's instead of ANGLE's GLESv2 library";
}
}
#endif
} }
IcdDispatch dispatch;
if (clIcdDispatch != nullptr)
{
static_cast<cl_icd_dispatch &>(dispatch) = *clIcdDispatch;
dispatch.clIcdGetPlatformIDsKHR = reinterpret_cast<clIcdGetPlatformIDsKHR_fn>(
clIcdDispatch->clGetExtensionFunctionAddress("clIcdGetPlatformIDsKHR"));
}
else if (error != nullptr)
{
ERR() << error;
}
return dispatch; return dispatch;
} }
......
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