Fix unit tests failing in CL/UNIT/TensorAllocator

The function pointer for clImportMemoryARM should be loaded in a portable way as recommended by Khronos® as outlined here:

https://registry.khronos.org/OpenCL/specs/3.0-unified/html/OpenCL_Ext.html#getting-opencl-api-extension-function-pointers

using clGetExtensionFunctionAddressForPlatform() call.

All extensions should ideally be loaded using the above mentioned function.

Resolves: COMPMID-6732

Signed-off-by: Gunes Bayir <gunes.bayir@arm.com>
Change-Id: I482b6bde721267d5e8c08301e5780d28a9c5ba85
Reviewed-on: https://review.mlplatform.org/c/ml/ComputeLibrary/+/10852
Benchmark: Arm Jenkins <bsgcomp@arm.com>
Tested-by: Arm Jenkins <bsgcomp@arm.com>
Reviewed-by: Jakub Sujak <jakub.sujak@arm.com>
Comments-Addressed: Arm Jenkins <bsgcomp@arm.com>
diff --git a/arm_compute/core/CL/OpenCL.h b/arm_compute/core/CL/OpenCL.h
index a5c4e39..8b5bf97 100644
--- a/arm_compute/core/CL/OpenCL.h
+++ b/arm_compute/core/CL/OpenCL.h
@@ -21,8 +21,8 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  */
-#ifndef ARM_COMPUTE_OPENCL_H
-#define ARM_COMPUTE_OPENCL_H
+#ifndef ACL_ARM_COMPUTE_CORE_CL_OPENCL_H
+#define ACL_ARM_COMPUTE_CORE_CL_OPENCL_H
 
 #include <string>
 #include <utility>
@@ -139,6 +139,7 @@
     DECLARE_FUNCTION_PTR(clWaitForEvents);
     DECLARE_FUNCTION_PTR(clCreateImage);
     DECLARE_FUNCTION_PTR(clSetKernelExecInfo);
+    DECLARE_FUNCTION_PTR(clGetExtensionFunctionAddressForPlatform);
 
     // Command buffer and mutable dispatch command buffer extensions
     DECLARE_FUNCTION_PTR(clCreateCommandBufferKHR);
@@ -159,4 +160,4 @@
     std::pair<bool, bool> _loaded;
 };
 } // namespace arm_compute
-#endif /* ARM_COMPUTE_OPENCL_H */
+#endif // ACL_ARM_COMPUTE_CORE_CL_OPENCL_H
diff --git a/src/core/CL/OpenCL.cpp b/src/core/CL/OpenCL.cpp
index 35421d0..07baa5e 100644
--- a/src/core/CL/OpenCL.cpp
+++ b/src/core/CL/OpenCL.cpp
@@ -132,6 +132,10 @@
     func_name##_ptr = reinterpret_cast<decltype(func_name) *>(dlsym(handle, #func_name));
 #endif /* __ANDROID__ */
 
+#define LOAD_EXTENSION_FUNCTION_PTR(func_name, platform_id) \
+    func_name##_ptr =                                       \
+        reinterpret_cast<decltype(func_name) *>(clGetExtensionFunctionAddressForPlatform(platform_id, #func_name));
+
     LOAD_FUNCTION_PTR(clCreateContext, handle);
     LOAD_FUNCTION_PTR(clCreateContextFromType, handle);
     LOAD_FUNCTION_PTR(clCreateCommandQueue, handle);
@@ -181,8 +185,27 @@
     LOAD_FUNCTION_PTR(clWaitForEvents, handle);
     LOAD_FUNCTION_PTR(clCreateImage, handle);
     LOAD_FUNCTION_PTR(clSetKernelExecInfo, handle);
+    LOAD_FUNCTION_PTR(clGetExtensionFunctionAddressForPlatform, handle);
+
+    // Load Extensions
+
+    // Number of platforms is assumed to be 1. For this to be greater than 1,
+    // the system must have more than one OpenCL implementation provided by
+    // different vendors. This is not our use case. Besides, the library
+    // already assumes one implementation as it uses one handle to load core
+    // functions.
+    constexpr unsigned int      num_platforms = 1U;
+    std::vector<cl_platform_id> platform_ids(num_platforms);
+    clGetPlatformIDs(num_platforms, platform_ids.data(), nullptr);
 
     // Command buffer and mutable dispatch command buffer extensions
+    /// TODO: (COMPMID-6742) Load Command Buffer extensions in a Portable way
+    /// using clGetExtensionFunctionAddressForPlatform().
+    /// The details can be found here:
+    ///    https://registry.khronos.org/OpenCL/specs/3.0-unified/html/OpenCL_Ext.html#getting-opencl-api-extension-function-pointers
+    ///
+    /// @note: There are some problems reported while loading these extensions in the recommended way.
+    ///        For details, please see COMPUTE-16545
     LOAD_FUNCTION_PTR(clCreateCommandBufferKHR, handle);
     LOAD_FUNCTION_PTR(clRetainCommandBufferKHR, handle);
     LOAD_FUNCTION_PTR(clReleaseCommandBufferKHR, handle);
@@ -193,9 +216,10 @@
     LOAD_FUNCTION_PTR(clUpdateMutableCommandsKHR, handle);
 
     // Third-party extensions
-    LOAD_FUNCTION_PTR(clImportMemoryARM, handle);
+    LOAD_EXTENSION_FUNCTION_PTR(clImportMemoryARM, platform_ids[0]);
 
 #undef LOAD_FUNCTION_PTR
+#undef LOAD_EXTENSION_FUNCTION_PTR
 
     //Don't call dlclose(handle) or all the symbols will be unloaded !
 
@@ -1063,6 +1087,19 @@
     }
 }
 
+void *clGetExtensionFunctionAddressForPlatform(cl_platform_id platform, const char *funcname)
+{
+    arm_compute::CLSymbols::get().load_default();
+    const auto func = arm_compute::CLSymbols::get().clGetExtensionFunctionAddressForPlatform_ptr;
+
+    if (func != nullptr)
+    {
+        return func(platform, funcname);
+    }
+
+    return nullptr;
+}
+
 cl_command_buffer_khr clCreateCommandBufferKHR(cl_uint                                 num_queues,
                                                const cl_command_queue                 *queues,
                                                const cl_command_buffer_properties_khr *properties,