1 // 2 // Copyright 2021 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 // dispatch.cpp: Implements a function to fetch the ANGLE OpenCL dispatch table. 7 8 #include "libOpenCL/dispatch.h" 9 10 #include "anglebase/no_destructor.h" 11 #include "common/debug.h" 12 #include "common/system_utils.h" 13 14 #include <memory> 15 16 #ifdef _WIN32 17 # include <windows.h> 18 #endif 19 20 namespace cl 21 { 22 23 namespace 24 { 25 EntryPointsLib()26std::unique_ptr<angle::Library> &EntryPointsLib() 27 { 28 static angle::base::NoDestructor<std::unique_ptr<angle::Library>> sEntryPointsLib; 29 return *sEntryPointsLib; 30 } 31 CreateDispatch()32IcdDispatch CreateDispatch() 33 { 34 const cl_icd_dispatch *clIcdDispatch = nullptr; 35 const char *error = nullptr; 36 37 // Try to find ANGLE's GLESv2 library in the consistent way, which might fail 38 // if the current library or a link to it is not in ANGLE's binary directory 39 EntryPointsLib().reset( 40 angle::OpenSharedLibrary(ANGLE_GLESV2_LIBRARY_NAME, angle::SearchType::ModuleDir)); 41 if (EntryPointsLib() && EntryPointsLib()->getNative() != nullptr) 42 { 43 EntryPointsLib()->getAs("gCLIcdDispatchTable", &clIcdDispatch); 44 if (clIcdDispatch == nullptr) 45 { 46 INFO() << "Found system's instead of ANGLE's GLESv2 library"; 47 } 48 } 49 else 50 { 51 error = "Not able to find GLESv2 library"; 52 } 53 54 // If not found try to find ANGLE's GLESv2 library in build path 55 if (clIcdDispatch == nullptr) 56 { 57 #ifdef _WIN32 58 // On Windows the build path 'ANGLE_GLESV2_LIBRARY_PATH' is provided by the build system 59 const char path[] = ANGLE_GLESV2_LIBRARY_PATH "\\" ANGLE_GLESV2_LIBRARY_NAME ".dll"; 60 // This function allows to load further dependent libraries from the same directory 61 HMODULE handle = LoadLibraryExA(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); 62 if (handle != nullptr) 63 { 64 clIcdDispatch = reinterpret_cast<const cl_icd_dispatch *>( 65 GetProcAddress(handle, "gCLIcdDispatchTable")); 66 if (clIcdDispatch == nullptr) 67 { 68 error = "Error loading CL dispatch table."; 69 } 70 } 71 #else 72 // On posix-compatible systems this will also search in the rpath, which is the build path 73 EntryPointsLib().reset( 74 angle::OpenSharedLibrary(ANGLE_GLESV2_LIBRARY_NAME, angle::SearchType::SystemDir)); 75 if (EntryPointsLib() && EntryPointsLib()->getNative() != nullptr) 76 { 77 EntryPointsLib()->getAs("gCLIcdDispatchTable", &clIcdDispatch); 78 if (clIcdDispatch == nullptr) 79 { 80 INFO() << "Found system's instead of ANGLE's GLESv2 library"; 81 } 82 } 83 #endif 84 } 85 86 IcdDispatch dispatch; 87 if (clIcdDispatch != nullptr) 88 { 89 static_cast<cl_icd_dispatch &>(dispatch) = *clIcdDispatch; 90 dispatch.clIcdGetPlatformIDsKHR = reinterpret_cast<clIcdGetPlatformIDsKHR_fn>( 91 clIcdDispatch->clGetExtensionFunctionAddress("clIcdGetPlatformIDsKHR")); 92 } 93 else if (error != nullptr) 94 { 95 ERR() << error; 96 } 97 return dispatch; 98 } 99 100 } // anonymous namespace 101 GetDispatch()102const IcdDispatch &GetDispatch() 103 { 104 static const IcdDispatch sDispatch(CreateDispatch()); 105 return sDispatch; 106 } 107 108 } // namespace cl 109