Skip to content

Commit e9153f0

Browse files
authored
[SYCL] Introduce interop handle for host task (#1747)
This patch is number one in series of patches for interop part of host task. This patch introduces `interop_handle` as described by https://github.com/codeplaysoftware/standards-proposals/blob/master/host_task/host_task.md proposal. Signed-off-by: Sergey Kanaev <sergey.kanaev@intel.com>
1 parent 894c10d commit e9153f0

File tree

4 files changed

+199
-0
lines changed

4 files changed

+199
-0
lines changed

sycl/include/CL/sycl/detail/cg.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <CL/sycl/detail/type_traits.hpp>
2121
#include <CL/sycl/group.hpp>
2222
#include <CL/sycl/id.hpp>
23+
#include <CL/sycl/interop_handle.hpp>
2324
#include <CL/sycl/interop_handler.hpp>
2425
#include <CL/sycl/kernel.hpp>
2526
#include <CL/sycl/nd_item.hpp>
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
//==------------ interop_handle.hpp --- SYCL interop handle ----------------==//
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+
#include <CL/sycl/access/access.hpp>
12+
#include <CL/sycl/accessor.hpp>
13+
#include <CL/sycl/backend_types.hpp>
14+
#include <CL/sycl/detail/accessor_impl.hpp>
15+
#include <CL/sycl/detail/common.hpp>
16+
#include <CL/sycl/detail/defines.hpp>
17+
#include <CL/sycl/detail/pi.hpp>
18+
19+
#include <memory>
20+
21+
__SYCL_INLINE_NAMESPACE(cl) {
22+
namespace sycl {
23+
24+
namespace detail {
25+
class AccessorBaseHost;
26+
class ExecCGCommand;
27+
class DispatchHostTask;
28+
class queue_impl;
29+
class device_impl;
30+
class context_impl;
31+
} // namespace detail
32+
33+
class queue;
34+
class device;
35+
class context;
36+
37+
class interop_handle {
38+
public:
39+
/// Receives a SYCL accessor that has been defined as a requirement for the
40+
/// command group, and returns the underlying OpenCL memory object that is
41+
/// used by the SYCL runtime. If the accessor passed as parameter is not part
42+
/// of the command group requirements (e.g. it is an unregistered placeholder
43+
/// accessor), the exception `cl::sycl::invalid_object` is thrown
44+
/// asynchronously.
45+
template <backend BackendName = backend::opencl, typename DataT, int Dims,
46+
access::mode Mode, access::target Target, access::placeholder IsPlh>
47+
typename std::enable_if<
48+
Target != access::target::host_buffer,
49+
typename interop<BackendName,
50+
accessor<DataT, Dims, Mode, Target, IsPlh>>::type>::type
51+
get_native_mem(const accessor<DataT, Dims, Mode, Target, IsPlh> &Acc) const {
52+
#ifndef __SYCL_DEVICE_ONLY__
53+
const auto *AccBase = static_cast<const detail::AccessorBaseHost *>(&Acc);
54+
return getMemImpl<BackendName, DataT, Dims, Mode, Target, IsPlh>(
55+
detail::getSyclObjImpl(*AccBase).get());
56+
#else
57+
(void)Acc;
58+
// we believe this won't be ever called on device side
59+
return nullptr;
60+
#endif
61+
}
62+
63+
template <backend BackendName = backend::opencl, typename DataT, int Dims,
64+
access::mode Mode, access::target Target, access::placeholder IsPlh>
65+
typename std::enable_if<
66+
Target == access::target::host_buffer,
67+
typename interop<BackendName,
68+
accessor<DataT, Dims, Mode, Target, IsPlh>>::type>::type
69+
get_native_mem(const accessor<DataT, Dims, Mode, Target, IsPlh> &) const {
70+
throw invalid_object_error("Getting memory object out of host accessor is "
71+
"not allowed",
72+
PI_INVALID_MEM_OBJECT);
73+
}
74+
75+
/// Returns an underlying OpenCL queue for the SYCL queue used to submit the
76+
/// command group, or the fallback queue if this command-group is re-trying
77+
/// execution on an OpenCL queue. The OpenCL command queue returned is
78+
/// implementation-defined in cases where the SYCL queue maps to multiple
79+
/// underlying OpenCL objects. It is responsibility of the SYCL runtime to
80+
/// ensure the OpenCL queue returned is in a state that can be used to
81+
/// dispatch work, and that other potential OpenCL command queues associated
82+
/// with the same SYCL command queue are not executing commands while the host
83+
/// task is executing.
84+
template <backend BackendName = backend::opencl>
85+
auto get_native_queue() const noexcept ->
86+
typename interop<BackendName, queue>::type {
87+
return reinterpret_cast<typename interop<BackendName, queue>::type>(
88+
getNativeQueue());
89+
}
90+
91+
/// Returns an underlying OpenCL device associated with the SYCL queue used
92+
/// to submit the command group, or the fallback queue if this command-group
93+
/// is re-trying execution on an OpenCL queue.
94+
template <backend BackendName = backend::opencl>
95+
auto get_native_device() const noexcept ->
96+
typename interop<BackendName, device>::type {
97+
return reinterpret_cast<typename interop<BackendName, device>::type>(
98+
getNativeDevice());
99+
}
100+
101+
/// Returns an underlying OpenCL context associated with the SYCL queue used
102+
/// to submit the command group, or the fallback queue if this command-group
103+
/// is re-trying execution on an OpenCL queue.
104+
template <backend BackendName = backend::opencl>
105+
auto get_native_context() const noexcept ->
106+
typename interop<BackendName, context>::type {
107+
return reinterpret_cast<typename interop<BackendName, context>::type>(
108+
getNativeContext());
109+
}
110+
111+
private:
112+
using ReqToMem = std::pair<detail::Requirement *, pi_mem>;
113+
114+
public:
115+
// TODO set c-tor private
116+
interop_handle(std::vector<ReqToMem> MemObjs,
117+
const std::shared_ptr<detail::queue_impl> &Queue,
118+
const std::shared_ptr<detail::device_impl> &Device,
119+
const std::shared_ptr<detail::context_impl> &Context)
120+
: MQueue(Queue), MDevice(Device), MContext(Context),
121+
MMemObjs(std::move(MemObjs)) {}
122+
123+
private:
124+
template <backend BackendName, typename DataT, int Dims, access::mode Mode,
125+
access::target Target, access::placeholder IsPlh>
126+
auto getMemImpl(detail::Requirement *Req) const ->
127+
typename interop<BackendName,
128+
accessor<DataT, Dims, Mode, Target, IsPlh>>::type {
129+
return reinterpret_cast<typename interop<
130+
BackendName, accessor<DataT, Dims, Mode, Target, IsPlh>>::type>(
131+
getNativeMem(Req));
132+
}
133+
134+
pi_native_handle getNativeMem(detail::Requirement *Req) const;
135+
pi_native_handle getNativeQueue() const;
136+
pi_native_handle getNativeDevice() const;
137+
pi_native_handle getNativeContext() const;
138+
139+
std::shared_ptr<detail::queue_impl> MQueue;
140+
std::shared_ptr<detail::device_impl> MDevice;
141+
std::shared_ptr<detail::context_impl> MContext;
142+
143+
std::vector<ReqToMem> MMemObjs;
144+
};
145+
146+
} // namespace sycl
147+
} // __SYCL_INLINE_NAMESPACE(cl)

sycl/source/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ set(SYCL_SOURCES
143143
"function_pointer.cpp"
144144
"half_type.cpp"
145145
"handler.cpp"
146+
"interop_handle.cpp"
146147
"interop_handler.cpp"
147148
"kernel.cpp"
148149
"platform.cpp"

sycl/source/interop_handle.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
//==------------ interop_handle.cpp --- SYCL interop handle ----------------==//
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/detail/accessor_impl.hpp>
10+
#include <CL/sycl/exception.hpp>
11+
#include <CL/sycl/interop_handle.hpp>
12+
#include <detail/context_impl.hpp>
13+
#include <detail/device_impl.hpp>
14+
#include <detail/queue_impl.hpp>
15+
16+
#include <algorithm>
17+
18+
__SYCL_INLINE_NAMESPACE(cl) {
19+
namespace sycl {
20+
21+
pi_native_handle interop_handle::getNativeMem(detail::Requirement *Req) const {
22+
auto Iter = std::find_if(std::begin(MMemObjs), std::end(MMemObjs),
23+
[=](ReqToMem Elem) { return (Elem.first == Req); });
24+
25+
if (Iter == std::end(MMemObjs)) {
26+
throw invalid_object_error("Invalid memory object used inside interop",
27+
PI_INVALID_MEM_OBJECT);
28+
}
29+
30+
auto Plugin = MQueue->getPlugin();
31+
pi_native_handle Handle;
32+
Plugin.call<detail::PiApiKind::piextMemGetNativeHandle>(Iter->second,
33+
&Handle);
34+
return Handle;
35+
}
36+
37+
pi_native_handle interop_handle::getNativeDevice() const {
38+
return MDevice->getNative();
39+
}
40+
41+
pi_native_handle interop_handle::getNativeContext() const {
42+
return MContext->getNative();
43+
}
44+
45+
pi_native_handle interop_handle::getNativeQueue() const {
46+
return MQueue->getNative();
47+
}
48+
49+
} // namespace sycl
50+
} // __SYCL_INLINE_NAMESPACE(cl)

0 commit comments

Comments
 (0)