Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[UR] Replace calls to UR in native handle functions to proper OpenCL functions #17016

Open
wants to merge 1 commit into
base: sycl
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions sycl/cmake/modules/AddSYCLUnitTest.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ macro(add_sycl_unittest test_dirname link_variant)
set(LLVM_REQUIRES_EH ON)
set(LLVM_REQUIRES_RTTI ON)

get_target_property(SYCL_BINARY_DIR sycl-toolchain BINARY_DIR)

string(TOLOWER "${CMAKE_BUILD_TYPE}" build_type_lower)
if (MSVC AND build_type_lower MATCHES "debug")
set(sycl_obj_target "sycld_object")
Expand Down Expand Up @@ -47,7 +49,7 @@ macro(add_sycl_unittest test_dirname link_variant)
SYCL_CONFIG_FILE_NAME=null.cfg
SYCL_DEVICELIB_NO_FALLBACK=1
SYCL_CACHE_DIR="${CMAKE_BINARY_DIR}/sycl_cache"
"PATH=${CMAKE_BINARY_DIR}/bin;$ENV{PATH}"
"PATH=${SYCL_BINARY_DIR}/unittests/lib;${CMAKE_BINARY_DIR}/bin;$ENV{PATH}"
${CMAKE_CURRENT_BINARY_DIR}/${test_dirname}
DEPENDS
${test_dirname}
Expand All @@ -59,7 +61,7 @@ macro(add_sycl_unittest test_dirname link_variant)
SYCL_CONFIG_FILE_NAME=null.cfg
SYCL_DEVICELIB_NO_FALLBACK=1
SYCL_CACHE_DIR="${CMAKE_BINARY_DIR}/sycl_cache"
"LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/lib:$ENV{LD_LIBRARY_PATH}"
"LD_LIBRARY_PATH=${SYCL_BINARY_DIR}/unittests/lib:${CMAKE_BINARY_DIR}/lib:$ENV{LD_LIBRARY_PATH}"
${CMAKE_CURRENT_BINARY_DIR}/${test_dirname}
DEPENDS
${test_dirname}
Expand All @@ -73,10 +75,11 @@ macro(add_sycl_unittest test_dirname link_variant)
LLVMTestingSupport
OpenCL-Headers
unified-runtime::mock
mockOpenCL
${SYCL_LINK_LIBS}
)

add_dependencies(${test_dirname} ur_adapter_mock)
add_dependencies(${test_dirname} ur_adapter_mock mockOpenCL)

if(SYCL_ENABLE_EXTENSION_JIT)
target_link_libraries(${test_dirname} PRIVATE sycl-jit)
Expand Down
18 changes: 18 additions & 0 deletions sycl/include/sycl/detail/os_util.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,24 @@ void fileTreeWalk(const std::string Path,
std::function<void(const std::string)> Func,
bool ignoreErrors = false);

void *dynLookup(const char *WinName, const char *LinName, const char *FunName);

// Look up a function name that was dynamically linked
// This is used by the runtime where it needs to manipulate native handles (e.g.
// retaining OpenCL handles). On Windows, the symbol name is looked up in
// `WinName`. In Linux, it uses `LinName`.
//
// The library must already have been loaded (perhaps by UR), otherwise this
// function throws.
template <typename fn>
fn *dynLookupFunction(const char *WinName, const char *LinName,
const char *FunName) {
return reinterpret_cast<fn *>(dynLookup(WinName, LinName, FunName));
}
#define __SYCL_OCL_GET_FUNCTION(FN) \
(::sycl::_V1::detail::dynLookupFunction<decltype(FN)>("OpenCL", \
"libOpenCL.so", #FN))

} // namespace detail
} // namespace _V1
} // namespace sycl
6 changes: 3 additions & 3 deletions sycl/source/backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ __SYCL_EXPORT event make_event(ur_native_handle_t NativeHandle,
std::make_shared<event_impl>(UrEvent, Context));

if (Backend == backend::opencl)
Adapter->call<UrApiKind::urEventRetain>(UrEvent);
__SYCL_OCL_GET_FUNCTION(clRetainEvent)(ur::cast<cl_event>(NativeHandle));
return Event;
}

Expand All @@ -205,7 +205,7 @@ make_kernel_bundle(ur_native_handle_t NativeHandle,
"urProgramCreateWithNativeHandle resulted in a null program handle.");

if (ContextImpl->getBackend() == backend::opencl)
Adapter->call<UrApiKind::urProgramRetain>(UrProgram);
__SYCL_OCL_GET_FUNCTION(clRetainProgram)(ur::cast<cl_program>(NativeHandle));

std::vector<ur_device_handle_t> ProgramDevices;
uint32_t NumDevices = 0;
Expand Down Expand Up @@ -352,7 +352,7 @@ kernel make_kernel(const context &TargetContext,
&UrKernel);

if (Backend == backend::opencl)
Adapter->call<UrApiKind::urKernelRetain>(UrKernel);
__SYCL_OCL_GET_FUNCTION(clRetainKernel)(ur::cast<cl_kernel>(NativeHandle));

// Construct the SYCL queue from UR queue.
return detail::createSyclObjFromImpl<kernel>(
Expand Down
2 changes: 1 addition & 1 deletion sycl/source/detail/buffer_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ buffer_impl::getNativeVector(backend BackendName) const {
auto Adapter = Platform->getAdapter();

if (Platform->getBackend() == backend::opencl) {
Adapter->call<UrApiKind::urMemRetain>(NativeMem);
__SYCL_OCL_GET_FUNCTION(clRetainMemObject)(ur::cast<cl_mem>(NativeMem));
}

ur_native_handle_t Handle = 0;
Expand Down
5 changes: 3 additions & 2 deletions sycl/source/detail/context_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -303,10 +303,11 @@ context_impl::findMatchingDeviceImpl(ur_device_handle_t &DeviceUR) const {

ur_native_handle_t context_impl::getNative() const {
const auto &Adapter = getAdapter();
if (getBackend() == backend::opencl)
Adapter->call<UrApiKind::urContextRetain>(getHandleRef());
ur_native_handle_t Handle;
Adapter->call<UrApiKind::urContextGetNativeHandle>(getHandleRef(), &Handle);
if (getBackend() == backend::opencl) {
__SYCL_OCL_GET_FUNCTION(clRetainContext)(ur::cast<cl_context>(Handle));
}
return Handle;
}

Expand Down
6 changes: 4 additions & 2 deletions sycl/source/detail/device_image_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -300,11 +300,13 @@ class device_image_impl {
const auto &ContextImplPtr = detail::getSyclObjImpl(MContext);
const AdapterPtr &Adapter = ContextImplPtr->getAdapter();

if (ContextImplPtr->getBackend() == backend::opencl)
Adapter->call<UrApiKind::urProgramRetain>(MProgram);
ur_native_handle_t NativeProgram = 0;
Adapter->call<UrApiKind::urProgramGetNativeHandle>(MProgram,
&NativeProgram);
if (ContextImplPtr->getBackend() == backend::opencl) {
auto *RetainFun = __SYCL_OCL_GET_FUNCTION(clRetainProgram);
RetainFun(ur::cast<cl_program>(NativeProgram));
}

return NativeProgram;
}
Expand Down
7 changes: 4 additions & 3 deletions sycl/source/detail/device_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ bool device_impl::is_affinity_supported(

cl_device_id device_impl::get() const {
// TODO catch an exception and put it to list of asynchronous exceptions
getAdapter()->call<UrApiKind::urDeviceRetain>(MDevice);
__SYCL_OCL_GET_FUNCTION(clRetainDevice)(ur::cast<cl_device_id>(getNative()));
return ur::cast<cl_device_id>(getNative());
}

Expand Down Expand Up @@ -345,10 +345,11 @@ std::vector<device> device_impl::create_sub_devices() const {

ur_native_handle_t device_impl::getNative() const {
auto Adapter = getAdapter();
if (getBackend() == backend::opencl)
Adapter->call<UrApiKind::urDeviceRetain>(getHandleRef());
ur_native_handle_t Handle;
Adapter->call<UrApiKind::urDeviceGetNativeHandle>(getHandleRef(), &Handle);
if (getBackend() == backend::opencl) {
__SYCL_OCL_GET_FUNCTION(clRetainDevice)(ur::cast<cl_device_id>(Handle));
}
return Handle;
}

Expand Down
4 changes: 2 additions & 2 deletions sycl/source/detail/event_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -500,10 +500,10 @@ ur_native_handle_t event_impl::getNative() {
this->setHandle(UREvent);
Handle = UREvent;
}
if (MContext->getBackend() == backend::opencl)
Adapter->call<UrApiKind::urEventRetain>(Handle);
ur_native_handle_t OutHandle;
Adapter->call<UrApiKind::urEventGetNativeHandle>(Handle, &OutHandle);
if (MContext->getBackend() == backend::opencl)
__SYCL_OCL_GET_FUNCTION(clRetainEvent)(ur::cast<cl_event>(OutHandle));
return OutHandle;
}

Expand Down
9 changes: 5 additions & 4 deletions sycl/source/detail/kernel_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,10 @@ class kernel_impl {
///
/// \return a valid cl_kernel instance
cl_kernel get() const {
getAdapter()->call<UrApiKind::urKernelRetain>(MKernel);
ur_native_handle_t nativeHandle = 0;
getAdapter()->call<UrApiKind::urKernelGetNativeHandle>(MKernel,
&nativeHandle);
__SYCL_OCL_GET_FUNCTION(clRetainKernel)(ur::cast<cl_kernel>(nativeHandle));
return ur::cast<cl_kernel>(nativeHandle);
}

Expand Down Expand Up @@ -179,12 +179,13 @@ class kernel_impl {
ur_native_handle_t getNative() const {
const AdapterPtr &Adapter = MContext->getAdapter();

if (MContext->getBackend() == backend::opencl)
Adapter->call<UrApiKind::urKernelRetain>(MKernel);

ur_native_handle_t NativeKernel = 0;
Adapter->call<UrApiKind::urKernelGetNativeHandle>(MKernel, &NativeKernel);

if (MContext->getBackend() == backend::opencl) {
__SYCL_OCL_GET_FUNCTION(clRetainKernel)(ur::cast<cl_kernel>(NativeKernel));
}

return NativeKernel;
}

Expand Down
32 changes: 32 additions & 0 deletions sycl/source/detail/os_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,38 @@ size_t getDirectorySize(const std::string &Path, bool ignoreErrors) {
return DirSizeVar;
}

// Look up a function name that was dynamically linked
// This is used by the runtime where it needs to manipulate native handles (e.g.
// retaining OpenCL handles). On Windows, the symbol name is looked up in
// `WinName`. In Linux, it uses `LinName`.
//
// The library must already have been loaded (perhaps by UR), otherwise this
// function throws.
void *dynLookup([[maybe_unused]] const char *WinName,
[[maybe_unused]] const char *LinName, const char *FunName) {
#ifdef _MSC_VER
auto handle = GetModuleHandleA(WinName);
if (!handle) {
throw sycl::exception(make_error_code(errc::runtime),
"OpenCL library is not loaded");
}
auto *retVal = GetProcAddress(handle, FunName);
#else
auto handle = dlopen(LinName, RTLD_LAZY | RTLD_NOLOAD);
if (!handle) {
throw sycl::exception(make_error_code(errc::runtime),
"OpenCL library is not loaded");
}
auto *retVal = dlsym(handle, FunName);
dlclose(handle);
#endif
if (!handle) {
throw sycl::exception(make_error_code(errc::runtime),
"OpenCL method could not be found");
}
return retVal;
}

} // namespace detail
} // namespace _V1
} // namespace sycl
6 changes: 4 additions & 2 deletions sycl/source/detail/queue_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -731,15 +731,17 @@ void queue_impl::destructorNotification() {

ur_native_handle_t queue_impl::getNative(int32_t &NativeHandleDesc) const {
const AdapterPtr &Adapter = getAdapter();
if (getContextImplPtr()->getBackend() == backend::opencl)
Adapter->call<UrApiKind::urQueueRetain>(MQueues[0]);
ur_native_handle_t Handle{};
ur_queue_native_desc_t UrNativeDesc{UR_STRUCTURE_TYPE_QUEUE_NATIVE_DESC,
nullptr, nullptr};
UrNativeDesc.pNativeData = &NativeHandleDesc;

Adapter->call<UrApiKind::urQueueGetNativeHandle>(MQueues[0], &UrNativeDesc,
&Handle);
if (getContextImplPtr()->getBackend() == backend::opencl) {
auto *RetainFn = __SYCL_OCL_GET_FUNCTION(clRetainCommandQueue);
RetainFn(ur::cast<cl_command_queue>(Handle));
}
return Handle;
}

Expand Down
3 changes: 2 additions & 1 deletion sycl/source/detail/queue_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -273,10 +273,11 @@ class queue_impl {
/// \return an OpenCL interoperability queue handle.

cl_command_queue get() {
getAdapter()->call<UrApiKind::urQueueRetain>(MQueues[0]);
ur_native_handle_t nativeHandle = 0;
getAdapter()->call<UrApiKind::urQueueGetNativeHandle>(MQueues[0], nullptr,
&nativeHandle);
auto *retainFn = __SYCL_OCL_GET_FUNCTION(clRetainCommandQueue);
retainFn(ur::cast<cl_command_queue>(nativeHandle));
return ur::cast<cl_command_queue>(nativeHandle);
}

Expand Down
10 changes: 6 additions & 4 deletions sycl/source/detail/sycl_mem_obj_t.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,9 @@ SYCLMemObjT::SYCLMemObjT(ur_native_handle_t MemObject,
make_error_code(errc::invalid),
"Input context must be the same as the context of cl_mem");

if (MInteropContext->getBackend() == backend::opencl)
Adapter->call<UrApiKind::urMemRetain>(MInteropMemObject);
if (MInteropContext->getBackend() == backend::opencl) {
__SYCL_OCL_GET_FUNCTION(clRetainMemObject)(ur::cast<cl_mem>(MemObject));
}
}

ur_mem_type_t getImageType(int Dimensions) {
Expand Down Expand Up @@ -112,8 +113,9 @@ SYCLMemObjT::SYCLMemObjT(ur_native_handle_t MemObject,
make_error_code(errc::invalid),
"Input context must be the same as the context of cl_mem");

if (MInteropContext->getBackend() == backend::opencl)
Adapter->call<UrApiKind::urMemRetain>(MInteropMemObject);
if (MInteropContext->getBackend() == backend::opencl) {
__SYCL_OCL_GET_FUNCTION(clRetainMemObject)(ur::cast<cl_mem>(MemObject));
}
}

void SYCLMemObjT::releaseMem(ContextImplPtr Context, void *MemAllocation) {
Expand Down
2 changes: 1 addition & 1 deletion sycl/source/device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ device::device(cl_device_id DeviceId) {
auto Platform =
detail::platform_impl::getPlatformFromUrDevice(Device, Adapter);
impl = Platform->getOrMakeDeviceImpl(Device, Platform);
Adapter->call<detail::UrApiKind::urDeviceRetain>(impl->getHandleRef());
__SYCL_OCL_GET_FUNCTION(clRetainDevice)(DeviceId);
}

device::device(const device_selector &deviceSelector) {
Expand Down
4 changes: 1 addition & 3 deletions sycl/source/event.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@ event::event(cl_event ClEvent, const context &SyclContext)
detail::ur::cast<ur_event_handle_t>(ClEvent), SyclContext)) {
// This is a special interop constructor for OpenCL, so the event must be
// retained.
// TODO(pi2ur): Don't just cast from cl_event above
impl->getAdapter()->call<detail::UrApiKind::urEventRetain>(
detail::ur::cast<ur_event_handle_t>(ClEvent));
__SYCL_OCL_GET_FUNCTION(clRetainEvent)(ClEvent);
}

bool event::operator==(const event &rhs) const { return rhs.impl == impl; }
Expand Down
2 changes: 1 addition & 1 deletion sycl/source/kernel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ kernel::kernel(cl_kernel ClKernel, const context &SyclContext) {
// This is a special interop constructor for OpenCL, so the kernel must be
// retained.
if (get_backend() == backend::opencl) {
impl->getAdapter()->call<detail::UrApiKind::urKernelRetain>(hKernel);
__SYCL_OCL_GET_FUNCTION(clRetainKernel)(ClKernel);
}
}

Expand Down
3 changes: 3 additions & 0 deletions sycl/test/Unit/lit.cfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,11 @@ def find_shlibpath_var():
for shlibpath_var in find_shlibpath_var():
# in stand-alone builds, shlibdir is clang's build tree
# while llvm_libs_dir is installed LLVM (and possibly older clang)
# For unit tests, we have a "mock" OpenCL which needs to have
# priority and so is at the start of the shlibpath list
shlibpath = os.path.pathsep.join(
(
os.path.join(config.test_exec_root, "lib"),
config.shlibdir,
config.llvm_libs_dir,
config.environment.get(shlibpath_var, ""),
Expand Down
2 changes: 2 additions & 0 deletions sycl/unittests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ string(TOLOWER "${CMAKE_BUILD_TYPE}" build_type_lower)

include(AddSYCLUnitTest)

add_subdirectory(mock_opencl)

add_custom_target(check-sycl-unittests)

add_subdirectory(ur)
Expand Down
7 changes: 3 additions & 4 deletions sycl/unittests/Extensions/CompositeDevice.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "sycl/platform.hpp"
#include <detail/device_impl.hpp>
#include <sycl/sycl.hpp>

#include <helpers/UrMock.hpp>
Expand Down Expand Up @@ -143,8 +144,7 @@ TEST(CompositeDeviceTest, PlatformExtOneAPIGetCompositeDevices) {
// We don't expect to see COMPOSITE_DEVICE_1 here, because one of its
// components (COMPONENT_DEVICE_D) is not available.
ASSERT_EQ(Composites.size(), 1u);
ASSERT_EQ(sycl::bit_cast<ur_device_handle_t>(
sycl::get_native<sycl::backend::opencl>(Composites.front())),
ASSERT_EQ(sycl::detail::getSyclObjImpl(Composites.front())->getHandleRef(),
COMPOSITE_DEVICE_0);
}

Expand All @@ -162,8 +162,7 @@ TEST(CompositeDeviceTest, SYCLExtOneAPIExperimentalGetCompositeDevices) {
// We don't expect to see COMPOSITE_DEVICE_1 here, because one of its
// components (COMPONENT_DEVICE_D) is not available.
ASSERT_EQ(Composites.size(), 1u);
ASSERT_EQ(sycl::bit_cast<ur_device_handle_t>(
sycl::get_native<sycl::backend::opencl>(Composites.front())),
ASSERT_EQ(sycl::detail::getSyclObjImpl(Composites.front())->getHandleRef(),
COMPOSITE_DEVICE_0);
}

Expand Down
Loading
Loading