Skip to content

Commit bbc2a9c

Browse files
committed
[SYCL] Add OpenCL interop API following SYCL-2020 backend generalization
Signed-off-by: Sergey V Maslov <[email protected]>
1 parent 4fdd0ab commit bbc2a9c

File tree

21 files changed

+323
-4
lines changed

21 files changed

+323
-4
lines changed

sycl/include/CL/sycl.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
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>
14+
//#include <CL/sycl/backend/opencl.hpp>
1515
#include <CL/sycl/buffer.hpp>
1616
#include <CL/sycl/builtins.hpp>
1717
#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 & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +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>(
179+
return detail::pi::cast<typename interop<BackendName, device>::type>(
180180
getNative());
181181
}
182182

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)

sycl/source/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ endfunction(add_sycl_rt_library)
9494

9595
set(SYCL_SOURCES
9696
"${sycl_inc_dir}/CL/sycl.hpp"
97+
"backend/opencl.cpp"
9798
"detail/accessor_impl.cpp"
9899
"detail/buffer_impl.cpp"
99100
"detail/builtins_common.cpp"

sycl/source/backend/opencl.cpp

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
//==------- opencl.cpp - SYCL OpenCL backend -------------------------------==//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include <CL/sycl.hpp>
10+
#include <detail/platform_impl.hpp>
11+
#include <detail/plugin.hpp>
12+
#include <detail/program_impl.hpp>
13+
#include <detail/queue_impl.hpp>
14+
15+
__SYCL_INLINE_NAMESPACE(cl) {
16+
namespace sycl {
17+
namespace opencl {
18+
using namespace detail;
19+
20+
//----------------------------------------------------------------------------
21+
// Implementation of opencl::make<platform>
22+
__SYCL_EXPORT platform make_platform(pi_native_handle NativeHandle) {
23+
const auto &Plugin = pi::getPlugin<backend::opencl>();
24+
// Create PI platform first.
25+
pi::PiPlatform PiPlatform;
26+
Plugin.call<PiApiKind::piextPlatformCreateWithNativeHandle>(NativeHandle,
27+
&PiPlatform);
28+
29+
// Construct the SYCL platform from PI platfrom.
30+
return detail::createSyclObjFromImpl<platform>(
31+
std::make_shared<platform_impl>(PiPlatform, Plugin));
32+
}
33+
34+
//----------------------------------------------------------------------------
35+
// Implementation of opencl::make<device>
36+
__SYCL_EXPORT device make_device(pi_native_handle NativeHandle) {
37+
const auto &Plugin = pi::getPlugin<backend::opencl>();
38+
// Create PI device first.
39+
pi::PiDevice PiDevice;
40+
Plugin.call<PiApiKind::piextDeviceCreateWithNativeHandle>(NativeHandle,
41+
&PiDevice);
42+
// Construct the SYCL device from PI device.
43+
return detail::createSyclObjFromImpl<device>(
44+
std::make_shared<device_impl>(PiDevice, Plugin));
45+
}
46+
47+
//----------------------------------------------------------------------------
48+
// Implementation of opencl::make<context>
49+
__SYCL_EXPORT context make_context(pi_native_handle NativeHandle) {
50+
const auto &Plugin = pi::getPlugin<backend::opencl>();
51+
// Create PI context first.
52+
pi::PiContext PiContext;
53+
Plugin.call<PiApiKind::piextContextCreateWithNativeHandle>(NativeHandle,
54+
&PiContext);
55+
// Construct the SYCL context from PI context.
56+
return detail::createSyclObjFromImpl<context>(
57+
std::make_shared<context_impl>(PiContext, async_handler{}, Plugin));
58+
}
59+
60+
//----------------------------------------------------------------------------
61+
// Implementation of opencl::make<program>
62+
__SYCL_EXPORT program make_program(const context &Context,
63+
pi_native_handle NativeHandle) {
64+
// Construct the SYCL program from native program.
65+
// TODO: move here the code that creates PI program, and remove the
66+
// native interop constructor.
67+
return detail::createSyclObjFromImpl<program>(
68+
std::make_shared<program_impl>(getSyclObjImpl(Context), NativeHandle));
69+
}
70+
71+
//----------------------------------------------------------------------------
72+
// Implementation of opencl::make<queue>
73+
__SYCL_EXPORT queue make_queue(const context &Context,
74+
pi_native_handle NativeHandle) {
75+
const auto &Plugin = pi::getPlugin<backend::opencl>();
76+
const auto &ContextImpl = getSyclObjImpl(Context);
77+
// Create PI queue first.
78+
pi::PiQueue PiQueue;
79+
Plugin.call<PiApiKind::piextQueueCreateWithNativeHandle>(NativeHandle,
80+
&PiQueue);
81+
// Construct the SYCL queue from PI queue.
82+
return detail::createSyclObjFromImpl<queue>(std::make_shared<queue_impl>(
83+
PiQueue, ContextImpl, ContextImpl->get_async_handler()));
84+
}
85+
86+
} // namespace opencl
87+
} // namespace sycl
88+
} // __SYCL_INLINE_NAMESPACE(cl)

sycl/source/detail/pi.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,25 @@ static void initializePlugins(vector_class<plugin> *Plugins) {
372372
#endif
373373
}
374374

375+
// Get the plugin serving given backend.
376+
template <backend BE> const plugin &getPlugin() {
377+
static const plugin *Plugin = nullptr;
378+
if (Plugin)
379+
return *Plugin;
380+
381+
const vector_class<plugin> &Plugins = pi::initialize();
382+
for (const auto &P : Plugins)
383+
if (P.getBackend() == BE) {
384+
Plugin = &P;
385+
return *Plugin;
386+
}
387+
388+
throw runtime_error("pi::getPlugin couldn't find plugin",
389+
PI_INVALID_OPERATION);
390+
}
391+
392+
template const plugin &getPlugin<backend::opencl>();
393+
375394
// Report error and no return (keeps compiler from printing warnings).
376395
// TODO: Probably change that to throw a catchable exception,
377396
// but for now it is useful to see every failure.

sycl/source/detail/platform_impl.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,13 @@ bool platform_impl::has_extension(const string_class &ExtensionName) const {
276276
return (AllExtensionNames.find(ExtensionName) != std::string::npos);
277277
}
278278

279+
pi_native_handle platform_impl::getNative() const {
280+
const auto &Plugin = getPlugin();
281+
pi_native_handle Handle;
282+
Plugin.call<PiApiKind::piextPlatformGetNativeHandle>(getHandleRef(), &Handle);
283+
return Handle;
284+
}
285+
279286
template <info::platform param>
280287
typename info::param_traits<info::platform, param>::return_type
281288
platform_impl::get_info() const {

sycl/source/detail/platform_impl.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,11 @@ class platform_impl {
120120
MPlugin = std::move(PluginPtr);
121121
}
122122

123+
/// Gets the native handle of the SYCL platform.
124+
///
125+
/// \return a native handle.
126+
pi_native_handle getNative() const;
127+
123128
private:
124129
bool MHostPlatform = false;
125130
RT::PiPlatform MPlatform = 0;

sycl/source/platform.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ platform::get_info() const {
4949
return impl->get_info<param>();
5050
}
5151

52+
pi_native_handle platform::getNative() const { return impl->getNative(); }
53+
5254
#define PARAM_TRAITS_SPEC(param_type, param, ret_type) \
5355
template __SYCL_EXPORT ret_type \
5456
platform::get_info<info::param_type::param>() const;

0 commit comments

Comments
 (0)