Skip to content

[SYCL] Use SYCL-2020 backend_return_t<> in interop_handle instead of … #3685

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

Merged
merged 2 commits into from
May 6, 2021
Merged
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
8 changes: 8 additions & 0 deletions sycl/include/CL/sycl/backend.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@ template <backend Backend> class backend_traits {
// TODO define errc once SYCL2020-style exceptions are supported.
};

template <backend Backend, typename SyclType>
using backend_input_t =
typename backend_traits<Backend>::template input_type<SyclType>;

template <backend Backend, typename SyclType>
using backend_return_t =
typename backend_traits<Backend>::template return_type<SyclType>;

template <backend BackendName, class SyclObjectT>
auto get_native(const SyclObjectT &Obj) ->
typename interop<BackendName, SyclObjectT>::type {
Expand Down
11 changes: 10 additions & 1 deletion sycl/include/CL/sycl/backend_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,16 @@ enum class backend : char {
all = 4
};

template <backend name, typename SYCLObjectT> struct interop;
template <backend Backend, typename SYCLObjectT> struct interop;

template <backend Backend> class backend_traits;

template <backend Backend, typename SYCLObjectT>
using backend_input_t =
typename backend_traits<Backend>::template input_type<SYCLObjectT>;
template <backend Backend, typename SYCLObjectT>
using backend_return_t =
typename backend_traits<Backend>::template return_type<SYCLObjectT>;

inline std::ostream &operator<<(std::ostream &Out, backend be) {
switch (be) {
Expand Down
115 changes: 61 additions & 54 deletions sycl/include/CL/sycl/interop_handle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,21 @@ class interop_handle {
/// of the command group requirements (e.g. it is an unregistered placeholder
/// accessor), the exception `cl::sycl::invalid_object` is thrown
/// asynchronously.
template <backend BackendName = backend::opencl, typename DataT, int Dims,
template <backend Backend = backend::opencl, typename DataT, int Dims,
access::mode Mode, access::target Target, access::placeholder IsPlh>
typename detail::enable_if_t<
Target == access::target::global_buffer ||
Target == access::target::constant_buffer,
typename interop<BackendName,
accessor<DataT, Dims, Mode, Target, IsPlh>>::type>
backend_return_t<Backend, buffer<DataT, Dims>>
get_native_mem(const accessor<DataT, Dims, Mode, Target, IsPlh> &Acc) const {
// TODO: the method is available when the target is target::device. Add it
// to the assert below when target::device enum is created.
static_assert(Target == access::target::global_buffer ||
Target == access::target::constant_buffer,
"The method is available only for target::device accessors");
#ifndef __SYCL_DEVICE_ONLY__
if (Backend != get_backend())
throw invalid_object_error("Incorrect backend argument was passed",
PI_INVALID_MEM_OBJECT);
const auto *AccBase = static_cast<const detail::AccessorBaseHost *>(&Acc);
return getMemImpl<BackendName, DataT, Dims, Mode, Target, IsPlh>(
return getMemImpl<Backend, DataT, Dims>(
detail::getSyclObjImpl(*AccBase).get());
#else
(void)Acc;
Expand All @@ -67,64 +71,71 @@ class interop_handle {
#endif
}

template <backend BackendName = backend::opencl, typename DataT, int Dims,
access::mode Mode, access::target Target, access::placeholder IsPlh>
typename detail::enable_if_t<
!(Target == access::target::global_buffer ||
Target == access::target::constant_buffer),
typename interop<BackendName,
accessor<DataT, Dims, Mode,
access::target::global_buffer, IsPlh>>::type>
get_native_mem(const accessor<DataT, Dims, Mode, Target, IsPlh> &) const {
throw invalid_object_error("Getting memory object out of accessor for "
"specified target is not allowed",
PI_INVALID_MEM_OBJECT);
}

/// Returns an underlying OpenCL queue for the SYCL queue used to submit the
/// command group, or the fallback queue if this command-group is re-trying
/// execution on an OpenCL queue. The OpenCL command queue returned is
/// Returns an underlying native backend object associated with teh queue
/// that the host task was submitted to. If the command group was submitted
/// with a secondary queue and the fall-back was triggered, the queue that
/// is associated with the interop_handle must be the fall-back queue.
/// The native backend object returned must be in a state where it is capable
/// of being used in a way appropriate for the associated SYCL backend. It is
/// implementation-defined in cases where the SYCL queue maps to multiple
/// underlying OpenCL objects. It is responsibility of the SYCL runtime to
/// ensure the OpenCL queue returned is in a state that can be used to
/// dispatch work, and that other potential OpenCL command queues associated
/// underlying backend objects. It is responsibility of the SYCL runtime to
/// ensure the backend queue returned is in a state that can be used to
/// dispatch work, and that other potential backend command queues associated
/// with the same SYCL command queue are not executing commands while the host
/// task is executing.
template <backend BackendName = backend::opencl>
auto get_native_queue() const noexcept ->
typename interop<BackendName, queue>::type {
template <backend Backend = backend::opencl>
backend_return_t<Backend, queue> get_native_queue() const {
#ifndef __SYCL_DEVICE_ONLY__
return reinterpret_cast<typename interop<BackendName, queue>::type>(
getNativeQueue());
// TODO: replace the exception thrown below with the SYCL-2020 exception
// with the error code 'errc::backend_mismatch' when those new exceptions
// are ready to be used.
if (Backend != get_backend())
throw invalid_object_error("Incorrect backend argument was passed",
PI_INVALID_MEM_OBJECT);
return reinterpret_cast<backend_return_t<Backend, queue>>(getNativeQueue());
#else
// we believe this won't be ever called on device side
return 0;
#endif
}

/// Returns an underlying OpenCL device associated with the SYCL queue used
/// to submit the command group, or the fallback queue if this command-group
/// is re-trying execution on an OpenCL queue.
template <backend BackendName = backend::opencl>
auto get_native_device() const noexcept ->
typename interop<BackendName, device>::type {
/// Returns the SYCL application interoperability native backend object
/// associated with the device associated with the SYCL queue that the host
/// task was submitted to. The native backend object returned must be in
/// a state where it is capable of being used in a way appropriate for
/// the associated SYCL backend.
template <backend Backend = backend::opencl>
backend_return_t<Backend, device> get_native_device() const {
#ifndef __SYCL_DEVICE_ONLY__
return reinterpret_cast<typename interop<BackendName, device>::type>(
// TODO: replace the exception thrown below with the SYCL-2020 exception
// with the error code 'errc::backend_mismatch' when those new exceptions
// are ready to be used.
if (Backend != get_backend())
throw invalid_object_error("Incorrect backend argument was passed",
PI_INVALID_MEM_OBJECT);
return reinterpret_cast<backend_return_t<Backend, device>>(
getNativeDevice());
#else
// we believe this won't be ever called on device side
return 0;
#endif
}

/// Returns an underlying OpenCL context associated with the SYCL queue used
/// to submit the command group, or the fallback queue if this command-group
/// is re-trying execution on an OpenCL queue.
template <backend BackendName = backend::opencl>
auto get_native_context() const noexcept ->
typename interop<BackendName, context>::type {
/// Returns the SYCL application interoperability native backend object
/// associated with the context associated with the SYCL queue that the host
/// task was submitted to. The native backend object returned must be in
/// a state where it is capable of being used in a way appropriate for
/// the associated SYCL backend.
template <backend Backend = backend::opencl>
backend_return_t<Backend, context> get_native_context() const {
#ifndef __SYCL_DEVICE_ONLY__
return reinterpret_cast<typename interop<BackendName, context>::type>(
// TODO: replace the exception thrown below with the SYCL-2020 exception
// with the error code 'errc::backend_mismatch' when those new exceptions
// are ready to be used.
if (Backend != get_backend())
throw invalid_object_error("Incorrect backend argument was passed",
PI_INVALID_MEM_OBJECT);
return reinterpret_cast<backend_return_t<Backend, context>>(
getNativeContext());
#else
// we believe this won't be ever called on device side
Expand All @@ -144,11 +155,9 @@ class interop_handle {
: MQueue(Queue), MDevice(Device), MContext(Context),
MMemObjs(std::move(MemObjs)) {}

template <backend BackendName, typename DataT, int Dims, access::mode Mode,
access::target Target, access::placeholder IsPlh>
auto getMemImpl(detail::Requirement *Req) const ->
typename interop<BackendName,
accessor<DataT, Dims, Mode, Target, IsPlh>>::type {
template <backend Backend, typename DataT, int Dims>
backend_return_t<Backend, buffer<DataT, Dims>>
getMemImpl(detail::Requirement *Req) const {
/*
Do not update this cast: a C-style cast is required here.

Expand All @@ -167,9 +176,7 @@ class interop_handle {
https://en.cppreference.com/w/cpp/language/reinterpret_cast
https://en.cppreference.com/w/cpp/language/explicit_cast
*/
return (typename interop<BackendName,
accessor<DataT, Dims, Mode, Target, IsPlh>>::type)(
getNativeMem(Req));
return (backend_return_t<Backend, buffer<DataT, Dims>>)(getNativeMem(Req));
}

__SYCL_EXPORT pi_native_handle getNativeMem(detail::Requirement *Req) const;
Expand Down