Skip to content

Commit 12e8549

Browse files
author
Alexander Batashev
authored
[SYCL] SYCL 2020 backend interoperability part 1 (#3354)
Provide OpenCL and L0 implementations for some of make_* functions. Link to the specification: https://www.khronos.org/registry/SYCL/specs/sycl-2020/html/sycl-2020.html#sec:backend-interoperability-make This patch implements the following functions: - `make_platform` - `make_device` - `make_context` - `make_queue` - `make_event` Next patches are going to bring support for: - make_* functions for kernels, kernel bundles, sampled/unsampled images. - backend traits - CUDA support
1 parent 90c79c7 commit 12e8549

File tree

12 files changed

+328
-52
lines changed

12 files changed

+328
-52
lines changed

sycl/include/CL/sycl/backend.hpp

+82
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,17 @@
1010

1111
#include <CL/sycl/accessor.hpp>
1212
#include <CL/sycl/backend_types.hpp>
13+
#include <CL/sycl/buffer.hpp>
14+
#include <CL/sycl/context.hpp>
15+
#include <CL/sycl/detail/backend_traits.hpp>
16+
#include <CL/sycl/detail/pi.hpp>
17+
#include <CL/sycl/device.hpp>
18+
#include <CL/sycl/event.hpp>
1319
#include <CL/sycl/exception.hpp>
20+
#include <CL/sycl/platform.hpp>
21+
#include <CL/sycl/queue.hpp>
22+
23+
#include <type_traits>
1424

1525
__SYCL_INLINE_NAMESPACE(cl) {
1626
namespace sycl {
@@ -34,5 +44,77 @@ auto get_native(const accessor<DataT, Dimensions, AccessMode, AccessTarget,
3444
AccessTarget, IsPlaceholder>>::type =
3545
delete;
3646

47+
namespace detail {
48+
__SYCL_EXPORT platform make_platform(pi_native_handle NativeHandle,
49+
backend Backend);
50+
__SYCL_EXPORT device make_device(pi_native_handle NativeHandle,
51+
backend Backend);
52+
__SYCL_EXPORT context make_context(pi_native_handle NativeHandle,
53+
const async_handler &Handler,
54+
backend Backend);
55+
__SYCL_EXPORT queue make_queue(pi_native_handle NativeHandle,
56+
const context &TargetContext,
57+
const async_handler &Handler, backend Backend);
58+
__SYCL_EXPORT event make_event(pi_native_handle NativeHandle,
59+
const context &TargetContext, backend Backend);
60+
} // namespace detail
61+
62+
template <backend Backend>
63+
typename std::enable_if<
64+
detail::InteropFeatureSupportMap<Backend>::MakePlatform == true,
65+
platform>::type
66+
make_platform(const typename interop<Backend, platform>::type &BackendObject) {
67+
return detail::make_platform(
68+
detail::pi::cast<pi_native_handle>(BackendObject), Backend);
69+
}
70+
71+
template <backend Backend>
72+
typename std::enable_if<
73+
detail::InteropFeatureSupportMap<Backend>::MakeDevice == true, device>::type
74+
make_device(const typename interop<Backend, device>::type &BackendObject) {
75+
return detail::make_device(detail::pi::cast<pi_native_handle>(BackendObject),
76+
Backend);
77+
}
78+
79+
template <backend Backend>
80+
typename std::enable_if<
81+
detail::InteropFeatureSupportMap<Backend>::MakeContext == true,
82+
context>::type
83+
make_context(const typename interop<Backend, context>::type &BackendObject,
84+
const async_handler &Handler = {}) {
85+
return detail::make_context(detail::pi::cast<pi_native_handle>(BackendObject),
86+
Handler, Backend);
87+
}
88+
89+
template <backend Backend>
90+
typename std::enable_if<
91+
detail::InteropFeatureSupportMap<Backend>::MakeQueue == true, queue>::type
92+
make_queue(const typename interop<Backend, queue>::type &BackendObject,
93+
const context &TargetContext, const async_handler Handler = {}) {
94+
return detail::make_queue(detail::pi::cast<pi_native_handle>(BackendObject),
95+
TargetContext, Handler, Backend);
96+
}
97+
98+
template <backend Backend>
99+
typename std::enable_if<
100+
detail::InteropFeatureSupportMap<Backend>::MakeEvent == true, event>::type
101+
make_event(const typename interop<Backend, event>::type &BackendObject,
102+
const context &TargetContext) {
103+
return detail::make_event(detail::pi::cast<pi_native_handle>(BackendObject),
104+
TargetContext, Backend);
105+
}
106+
107+
template <backend Backend, typename T, int Dimensions = 1,
108+
typename AllocatorT = buffer_allocator>
109+
typename std::enable_if<detail::InteropFeatureSupportMap<Backend>::MakeBuffer ==
110+
true,
111+
buffer<T, Dimensions, AllocatorT>>::type
112+
make_buffer(
113+
const typename interop<Backend, buffer<T, Dimensions, AllocatorT>>::type
114+
&BackendObject,
115+
const context &TargetContext, event AvailableEvent = {}) {
116+
return buffer<T, Dimensions, AllocatorT>(
117+
reinterpret_cast<cl_mem>(BackendObject), TargetContext, AvailableEvent);
118+
}
37119
} // namespace sycl
38120
} // __SYCL_INLINE_NAMESPACE(cl)

sycl/include/CL/sycl/backend/level_zero.hpp

+12
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,18 @@ struct interop<backend::level_zero, accessor<DataT, Dimensions, AccessMode,
4949
using type = char *;
5050
};
5151

52+
namespace detail {
53+
template <> struct InteropFeatureSupportMap<backend::level_zero> {
54+
static constexpr bool MakePlatform = true;
55+
static constexpr bool MakeDevice = false;
56+
static constexpr bool MakeContext = false;
57+
static constexpr bool MakeQueue = false;
58+
static constexpr bool MakeEvent = false;
59+
static constexpr bool MakeBuffer = false;
60+
static constexpr bool MakeKernel = false;
61+
};
62+
} // namespace detail
63+
5264
namespace level_zero {
5365

5466
// Since Level-Zero is not doing any reference counting itself, we have to

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

+18
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#include <CL/sycl/accessor.hpp>
1313
#include <CL/sycl/backend_types.hpp>
14+
#include <CL/sycl/detail/backend_traits.hpp>
1415
#include <CL/sycl/detail/cl.h>
1516

1617
__SYCL_INLINE_NAMESPACE(cl) {
@@ -52,6 +53,23 @@ struct interop<backend::opencl, accessor<DataT, Dimensions, AccessMode,
5253
using type = cl_mem;
5354
};
5455

56+
template <typename DataT, int Dimensions, typename AllocatorT>
57+
struct interop<backend::opencl, buffer<DataT, Dimensions, AllocatorT>> {
58+
using type = cl_mem;
59+
};
60+
61+
namespace detail {
62+
template <> struct InteropFeatureSupportMap<backend::opencl> {
63+
static constexpr bool MakePlatform = true;
64+
static constexpr bool MakeDevice = true;
65+
static constexpr bool MakeContext = true;
66+
static constexpr bool MakeQueue = true;
67+
static constexpr bool MakeEvent = true;
68+
static constexpr bool MakeBuffer = true;
69+
static constexpr bool MakeKernel = true;
70+
};
71+
} // namespace detail
72+
5573
namespace opencl {
5674

5775
// Implementation of various "make" functions resides in SYCL RT because
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//==-------------- backend_traits.hpp - SYCL backend traits ----------------==//
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+
#pragma once
10+
11+
__SYCL_INLINE_NAMESPACE(cl) {
12+
namespace sycl {
13+
namespace detail {
14+
template <backend Backend> struct InteropFeatureSupportMap {
15+
static constexpr bool MakePlatform = false;
16+
static constexpr bool MakeDevice = false;
17+
static constexpr bool MakeContext = false;
18+
static constexpr bool MakeQueue = false;
19+
static constexpr bool MakeEvent = false;
20+
static constexpr bool MakeBuffer = false;
21+
static constexpr bool MakeKernel = false;
22+
};
23+
} // namespace detail
24+
} // namespace sycl
25+
} // __SYCL_INLINE_NAMESPACE(cl)

sycl/include/CL/sycl/platform.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#pragma once
10+
#include <CL/sycl/aspects.hpp>
1011
#include <CL/sycl/detail/common.hpp>
1112
#include <CL/sycl/detail/export.hpp>
1213
#include <CL/sycl/stl.hpp>

sycl/source/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ set(SYCL_SOURCES
102102
"${sycl_inc_dir}/CL/sycl.hpp"
103103
"backend/opencl.cpp"
104104
"backend/level_zero.cpp"
105+
"backend.cpp"
105106
"detail/accessor_impl.cpp"
106107
"detail/buffer_impl.cpp"
107108
"detail/builtins_common.cpp"

sycl/source/backend.cpp

+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
//==------------------- backend.cpp ----------------------------------------==//
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 "detail/context_impl.hpp"
10+
#include "detail/event_impl.hpp"
11+
#include "detail/platform_impl.hpp"
12+
#include "detail/plugin.hpp"
13+
#include "detail/queue_impl.hpp"
14+
#include <CL/sycl/backend.hpp>
15+
#include <CL/sycl/detail/export.hpp>
16+
#include <CL/sycl/detail/pi.h>
17+
#include <CL/sycl/exception_list.hpp>
18+
19+
__SYCL_INLINE_NAMESPACE(cl) {
20+
namespace sycl {
21+
namespace detail {
22+
23+
static const plugin &getPlugin(backend Backend) {
24+
switch (Backend) {
25+
case backend::opencl:
26+
return pi::getPlugin<backend::opencl>();
27+
case backend::level_zero:
28+
return pi::getPlugin<backend::level_zero>();
29+
default:
30+
throw sycl::runtime_error{"Unsupported backend", PI_INVALID_OPERATION};
31+
}
32+
}
33+
34+
platform make_platform(pi_native_handle NativeHandle, backend Backend) {
35+
const auto &Plugin = getPlugin(Backend);
36+
37+
// Create PI platform first.
38+
pi::PiPlatform PiPlatform = nullptr;
39+
Plugin.call<PiApiKind::piextPlatformCreateWithNativeHandle>(NativeHandle,
40+
&PiPlatform);
41+
42+
return detail::createSyclObjFromImpl<platform>(
43+
platform_impl::getOrMakePlatformImpl(PiPlatform, Plugin));
44+
}
45+
46+
__SYCL_EXPORT device make_device(pi_native_handle NativeHandle,
47+
backend Backend) {
48+
const auto &Plugin = getPlugin(Backend);
49+
50+
pi::PiDevice PiDevice = nullptr;
51+
Plugin.call<PiApiKind::piextDeviceCreateWithNativeHandle>(NativeHandle,
52+
nullptr, &PiDevice);
53+
// Construct the SYCL device from PI device.
54+
return detail::createSyclObjFromImpl<device>(
55+
std::make_shared<device_impl>(PiDevice, Plugin));
56+
}
57+
58+
__SYCL_EXPORT context make_context(pi_native_handle NativeHandle,
59+
const async_handler &Handler,
60+
backend Backend) {
61+
const auto &Plugin = getPlugin(Backend);
62+
63+
pi::PiContext PiContext = nullptr;
64+
Plugin.call<PiApiKind::piextContextCreateWithNativeHandle>(
65+
NativeHandle, 0, nullptr, false, &PiContext);
66+
// Construct the SYCL context from PI context.
67+
return detail::createSyclObjFromImpl<context>(
68+
std::make_shared<context_impl>(PiContext, Handler, Plugin));
69+
}
70+
71+
__SYCL_EXPORT queue make_queue(pi_native_handle NativeHandle,
72+
const context &Context,
73+
const async_handler &Handler, backend Backend) {
74+
const auto &Plugin = getPlugin(Backend);
75+
const auto &ContextImpl = getSyclObjImpl(Context);
76+
// Create PI queue first.
77+
pi::PiQueue PiQueue = nullptr;
78+
Plugin.call<PiApiKind::piextQueueCreateWithNativeHandle>(
79+
NativeHandle, ContextImpl->getHandleRef(), &PiQueue);
80+
// Construct the SYCL queue from PI queue.
81+
return detail::createSyclObjFromImpl<queue>(
82+
std::make_shared<queue_impl>(PiQueue, ContextImpl, Handler));
83+
}
84+
85+
__SYCL_EXPORT event make_event(pi_native_handle NativeHandle,
86+
const context &Context, backend Backend) {
87+
const auto &Plugin = getPlugin(Backend);
88+
89+
pi::PiEvent PiEvent = nullptr;
90+
Plugin.call<PiApiKind::piextEventCreateWithNativeHandle>(NativeHandle,
91+
&PiEvent);
92+
93+
return detail::createSyclObjFromImpl<event>(
94+
std::make_shared<event_impl>(PiEvent, Context));
95+
}
96+
97+
} // namespace detail
98+
} // namespace sycl
99+
} // __SYCL_INLINE_NAMESPACE(cl)

sycl/source/backend/level_zero.cpp

+5-16
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include <CL/sycl.hpp>
10+
#include <CL/sycl/backend.hpp>
1011
#include <detail/platform_impl.hpp>
1112
#include <detail/plugin.hpp>
1213
#include <detail/program_impl.hpp>
@@ -20,14 +21,7 @@ using namespace detail;
2021
//----------------------------------------------------------------------------
2122
// Implementation of level_zero::make<platform>
2223
__SYCL_EXPORT platform make_platform(pi_native_handle NativeHandle) {
23-
const auto &Plugin = pi::getPlugin<backend::level_zero>();
24-
// Create PI platform first.
25-
pi::PiPlatform PiPlatform;
26-
Plugin.call<PiApiKind::piextPlatformCreateWithNativeHandle>(NativeHandle,
27-
&PiPlatform);
28-
29-
return detail::createSyclObjFromImpl<platform>(
30-
platform_impl::getOrMakePlatformImpl(PiPlatform, Plugin));
24+
return detail::make_platform(NativeHandle, backend::level_zero);
3125
}
3226

3327
//----------------------------------------------------------------------------
@@ -86,15 +80,10 @@ __SYCL_EXPORT program make_program(const context &Context,
8680
// Implementation of level_zero::make<queue>
8781
__SYCL_EXPORT queue make_queue(const context &Context,
8882
pi_native_handle NativeHandle) {
89-
const auto &Plugin = pi::getPlugin<backend::level_zero>();
9083
const auto &ContextImpl = getSyclObjImpl(Context);
91-
// Create PI queue first.
92-
pi::PiQueue PiQueue;
93-
Plugin.call<PiApiKind::piextQueueCreateWithNativeHandle>(
94-
NativeHandle, ContextImpl->getHandleRef(), &PiQueue);
95-
// Construct the SYCL queue from PI queue.
96-
return detail::createSyclObjFromImpl<queue>(std::make_shared<queue_impl>(
97-
PiQueue, ContextImpl, ContextImpl->get_async_handler()));
84+
return detail::make_queue(NativeHandle, Context,
85+
ContextImpl->get_async_handler(),
86+
backend::level_zero);
9887
}
9988

10089
} // namespace level_zero

sycl/source/backend/opencl.cpp

+5-33
Original file line numberDiff line numberDiff line change
@@ -20,41 +20,19 @@ using namespace detail;
2020
//----------------------------------------------------------------------------
2121
// Implementation of opencl::make<platform>
2222
__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));
23+
return detail::make_platform(NativeHandle, backend::opencl);
3224
}
3325

3426
//----------------------------------------------------------------------------
3527
// Implementation of opencl::make<device>
3628
__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-
nullptr, &PiDevice);
42-
// Construct the SYCL device from PI device.
43-
return detail::createSyclObjFromImpl<device>(
44-
std::make_shared<device_impl>(PiDevice, Plugin));
29+
return detail::make_device(NativeHandle, backend::opencl);
4530
}
4631

4732
//----------------------------------------------------------------------------
4833
// Implementation of opencl::make<context>
4934
__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>(
54-
NativeHandle, 0, nullptr, false, &PiContext);
55-
// Construct the SYCL context from PI context.
56-
return detail::createSyclObjFromImpl<context>(
57-
std::make_shared<context_impl>(PiContext, async_handler{}, Plugin));
35+
return detail::make_context(NativeHandle, async_handler{}, backend::opencl);
5836
}
5937

6038
//----------------------------------------------------------------------------
@@ -72,15 +50,9 @@ __SYCL_EXPORT program make_program(const context &Context,
7250
// Implementation of opencl::make<queue>
7351
__SYCL_EXPORT queue make_queue(const context &Context,
7452
pi_native_handle NativeHandle) {
75-
const auto &Plugin = pi::getPlugin<backend::opencl>();
7653
const auto &ContextImpl = getSyclObjImpl(Context);
77-
// Create PI queue first.
78-
pi::PiQueue PiQueue;
79-
Plugin.call<PiApiKind::piextQueueCreateWithNativeHandle>(
80-
NativeHandle, ContextImpl->getHandleRef(), &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()));
54+
return detail::make_queue(NativeHandle, Context,
55+
ContextImpl->get_async_handler(), backend::opencl);
8456
}
8557

8658
} // namespace opencl

0 commit comments

Comments
 (0)