Skip to content

Commit bae0639

Browse files
[SYCL] Add OpenCL interop API following SYCL-2020 backend generalization (#1846)
The implementation is following https://github.com/KhronosGroup/SYCL-Shared/blob/master/proposals/sycl_generalization.md. It is OpenCL centric, and a Level-Zero counterpart is coming here: #1723 An important "side-effect" is that plugins are initialized from these APIs and not only from get_platforms() in the current state. Signed-off-by: Sergey V Maslov <[email protected]>
1 parent 19e3cf9 commit bae0639

File tree

21 files changed

+322
-5
lines changed

21 files changed

+322
-5
lines changed

sycl/include/CL/sycl.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
#include <CL/sycl/accessor.hpp>
1212
#include <CL/sycl/atomic.hpp>
1313
#include <CL/sycl/backend.hpp>
14-
#include <CL/sycl/backend/opencl.hpp>
1514
#include <CL/sycl/buffer.hpp>
1615
#include <CL/sycl/builtins.hpp>
1716
#include <CL/sycl/context.hpp>

sycl/include/CL/sycl/backend/opencl.hpp

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,83 @@
1616
__SYCL_INLINE_NAMESPACE(cl) {
1717
namespace sycl {
1818

19+
template <> struct interop<backend::opencl, platform> {
20+
using type = cl_platform_id;
21+
};
22+
23+
template <> struct interop<backend::opencl, device> {
24+
using type = cl_device_id;
25+
};
26+
27+
template <> struct interop<backend::opencl, context> {
28+
using type = cl_context;
29+
};
30+
1931
template <> struct interop<backend::opencl, queue> {
2032
using type = cl_command_queue;
2133
};
2234

35+
template <> struct interop<backend::opencl, program> {
36+
using type = cl_program;
37+
};
38+
2339
template <typename DataT, int Dimensions, access::mode AccessMode>
2440
struct interop<backend::opencl, accessor<DataT, Dimensions, AccessMode,
2541
access::target::global_buffer,
2642
access::placeholder::false_t>> {
2743
using type = cl_mem;
2844
};
2945

46+
namespace opencl {
47+
48+
// Implementation of various "make" functions resides in SYCL RT because
49+
// creating SYCL objects requires knowing details not acessible here.
50+
// Note that they take opaque pi_native_handle that real OpenCL handles
51+
// are casted to.
52+
//
53+
platform make_platform(pi_native_handle NativeHandle);
54+
device make_device(pi_native_handle NativeHandle);
55+
context make_context(pi_native_handle NativeHandle);
56+
program make_program(const context &Context, pi_native_handle NativeHandle);
57+
queue make_queue(const context &Context, pi_native_handle InteropHandle);
58+
59+
// Construction of SYCL platform.
60+
template <typename T, typename std::enable_if<
61+
std::is_same<T, platform>::value>::type * = nullptr>
62+
T make(typename interop<backend::opencl, T>::type Interop) {
63+
return make_platform(detail::pi::cast<pi_native_handle>(Interop));
64+
}
65+
66+
// Construction of SYCL device.
67+
template <typename T, typename std::enable_if<
68+
std::is_same<T, device>::value>::type * = nullptr>
69+
T make(typename interop<backend::opencl, T>::type Interop) {
70+
return make_device(detail::pi::cast<pi_native_handle>(Interop));
71+
}
72+
73+
// Construction of SYCL context.
74+
template <typename T, typename std::enable_if<
75+
std::is_same<T, context>::value>::type * = nullptr>
76+
T make(typename interop<backend::opencl, T>::type Interop) {
77+
return make_context(detail::pi::cast<pi_native_handle>(Interop));
78+
}
79+
80+
// Construction of SYCL program.
81+
template <typename T, typename std::enable_if<
82+
std::is_same<T, program>::value>::type * = nullptr>
83+
T make(const context &Context,
84+
typename interop<backend::opencl, T>::type Interop) {
85+
return make_program(Context, detail::pi::cast<pi_native_handle>(Interop));
86+
}
87+
88+
// Construction of SYCL queue.
89+
template <typename T, typename std::enable_if<
90+
std::is_same<T, queue>::value>::type * = nullptr>
91+
T make(const context &Context,
92+
typename interop<backend::opencl, T>::type Interop) {
93+
return make_queue(Context, detail::pi::cast<pi_native_handle>(Interop));
94+
}
95+
96+
} // namespace opencl
3097
} // namespace sycl
3198
} // __SYCL_INLINE_NAMESPACE(cl)

sycl/include/CL/sycl/detail/pi.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
// Platform
1818
_PI_API(piPlatformsGet)
1919
_PI_API(piPlatformGetInfo)
20+
_PI_API(piextPlatformGetNativeHandle)
21+
_PI_API(piextPlatformCreateWithNativeHandle)
2022
// Device
2123
_PI_API(piDevicesGet)
2224
_PI_API(piDeviceGetInfo)

sycl/include/CL/sycl/detail/pi.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -805,6 +805,21 @@ __SYCL_EXPORT pi_result piPlatformGetInfo(pi_platform platform,
805805
void *param_value,
806806
size_t *param_value_size_ret);
807807

808+
/// Gets the native handle of a PI platform object.
809+
///
810+
/// \param platform is the PI platform to get the native handle of.
811+
/// \param nativeHandle is the native handle of platform.
812+
__SYCL_EXPORT pi_result piextPlatformGetNativeHandle(
813+
pi_platform platform, pi_native_handle *nativeHandle);
814+
815+
/// Creates PI platform object from a native handle.
816+
/// NOTE: The created PI object takes ownership of the native handle.
817+
///
818+
/// \param nativeHandle is the native handle to create PI device from.
819+
/// \param platform is the PI platform created from the native handle.
820+
__SYCL_EXPORT pi_result piextPlatformCreateWithNativeHandle(
821+
pi_native_handle nativeHandle, pi_platform *platform);
822+
808823
__SYCL_EXPORT pi_result piDevicesGet(pi_platform platform,
809824
pi_device_type device_type,
810825
pi_uint32 num_entries, pi_device *devices,

sycl/include/CL/sycl/detail/pi.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,9 @@ extern std::shared_ptr<plugin> GlobalPlugin;
139139
// Performs PI one-time initialization.
140140
const vector_class<plugin> &initialize();
141141

142+
// Get the plugin serving given backend.
143+
template <backend BE> const plugin &getPlugin();
144+
142145
// Utility Functions to get Function Name for a PI Api.
143146
template <PiApiKind PiApiOffset> struct PiFuncInfo {};
144147

sycl/include/CL/sycl/device.hpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,7 @@ class __SYCL_EXPORT device {
176176
/// \return a native handle, the type of which defined by the backend.
177177
template <backend BackendName>
178178
auto get_native() const -> typename interop<BackendName, device>::type {
179-
return static_cast<typename interop<BackendName, device>::type>(
180-
getNative());
179+
return (typename interop<BackendName, device>::type)getNative();
181180
}
182181

183182
private:

sycl/include/CL/sycl/platform.hpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,18 @@ class __SYCL_EXPORT platform {
102102
/// \return a vector of all available SYCL platforms.
103103
static vector_class<platform> get_platforms();
104104

105+
/// Gets the native handle of the SYCL platform.
106+
///
107+
/// \return a native handle, the type of which defined by the backend.
108+
template <backend BackendName>
109+
auto get_native() const -> typename interop<BackendName, platform>::type {
110+
return detail::pi::cast<typename interop<BackendName, platform>::type>(
111+
getNative());
112+
}
113+
105114
private:
115+
pi_native_handle getNative() const;
116+
106117
shared_ptr_class<detail::platform_impl> impl;
107118
platform(shared_ptr_class<detail::platform_impl> impl) : impl(impl) {}
108119

sycl/include/CL/sycl/queue.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -703,8 +703,12 @@ class __SYCL_EXPORT queue {
703703
pi_native_handle getNative() const;
704704

705705
shared_ptr_class<detail::queue_impl> impl;
706+
queue(shared_ptr_class<detail::queue_impl> impl) : impl(impl) {}
707+
706708
template <class Obj>
707709
friend decltype(Obj::impl) detail::getSyclObjImpl(const Obj &SyclObject);
710+
template <class T>
711+
friend T detail::createSyclObjFromImpl(decltype(T::impl) ImplObj);
708712

709713
/// A template-free version of submit.
710714
event submit_impl(function_class<void(handler &)> CGH,

sycl/plugins/level_zero/pi_level0.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,28 @@ pi_result piPlatformGetInfo(pi_platform Platform, pi_platform_info ParamName,
565565
return PI_SUCCESS;
566566
}
567567

568+
pi_result piextPlatformGetNativeHandle(pi_platform Platform,
569+
pi_native_handle *NativeHandle) {
570+
assert(Platform);
571+
assert(NativeHandle);
572+
573+
auto ZeDriver = pi_cast<ze_driver_handle_t *>(NativeHandle);
574+
// Extract the L0 driver handle from the given PI platform
575+
*ZeDriver = Platform->ZeDriver;
576+
return PI_SUCCESS;
577+
}
578+
579+
pi_result piextPlatformCreateWithNativeHandle(pi_native_handle NativeHandle,
580+
pi_platform *Platform) {
581+
assert(NativeHandle);
582+
assert(Platform);
583+
584+
// Create PI platform from the given L0 driver handle.
585+
auto ZeDriver = pi_cast<ze_driver_handle_t>(NativeHandle);
586+
*Platform = new _pi_platform(ZeDriver);
587+
return PI_SUCCESS;
588+
}
589+
568590
pi_result piDevicesGet(pi_platform Platform, pi_device_type DeviceType,
569591
pi_uint32 NumEntries, pi_device *Devices,
570592
pi_uint32 *NumDevices) {

sycl/plugins/opencl/pi_opencl.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,14 @@ pi_result piPlatformsGet(pi_uint32 num_entries, pi_platform *platforms,
176176
return static_cast<pi_result>(result);
177177
}
178178

179+
pi_result piextPlatformCreateWithNativeHandle(pi_native_handle nativeHandle,
180+
pi_platform *platform) {
181+
assert(platform);
182+
assert(nativeHandle);
183+
*platform = reinterpret_cast<pi_platform>(nativeHandle);
184+
return PI_SUCCESS;
185+
}
186+
179187
// Example of a PI interface that does not map exactly to an OpenCL one.
180188
pi_result piDevicesGet(pi_platform platform, pi_device_type device_type,
181189
pi_uint32 num_entries, pi_device *devices,
@@ -1072,6 +1080,11 @@ static pi_result piextGetNativeHandle(void *piObj,
10721080
return PI_SUCCESS;
10731081
}
10741082

1083+
pi_result piextPlatformGetNativeHandle(pi_platform platform,
1084+
pi_native_handle *nativeHandle) {
1085+
return piextGetNativeHandle(platform, nativeHandle);
1086+
}
1087+
10751088
pi_result piextDeviceGetNativeHandle(pi_device device,
10761089
pi_native_handle *nativeHandle) {
10771090
return piextGetNativeHandle(device, nativeHandle);
@@ -1113,6 +1126,9 @@ pi_result piPluginInit(pi_plugin *PluginInit) {
11131126
// Platform
11141127
_PI_CL(piPlatformsGet, piPlatformsGet)
11151128
_PI_CL(piPlatformGetInfo, clGetPlatformInfo)
1129+
_PI_CL(piextPlatformGetNativeHandle, piextPlatformGetNativeHandle)
1130+
_PI_CL(piextPlatformCreateWithNativeHandle,
1131+
piextPlatformCreateWithNativeHandle)
11161132
// Device
11171133
_PI_CL(piDevicesGet, piDevicesGet)
11181134
_PI_CL(piDeviceGetInfo, clGetDeviceInfo)

0 commit comments

Comments
 (0)