diff --git a/sycl/include/CL/sycl/backend.hpp b/sycl/include/CL/sycl/backend.hpp index 9edca021dca6b..921cba381de38 100644 --- a/sycl/include/CL/sycl/backend.hpp +++ b/sycl/include/CL/sycl/backend.hpp @@ -10,6 +10,7 @@ #include #include +#include __SYCL_INLINE_NAMESPACE(cl) { namespace sycl { @@ -17,6 +18,9 @@ namespace sycl { template auto get_native(const SyclObjectT &Obj) -> typename interop::type { + // TODO use SYCL 2020 exception when implemented + if (Obj.get_backend() != BackendName) + throw runtime_error("Backends mismatch", PI_INVALID_OPERATION); return Obj.template get_native(); } diff --git a/sycl/include/CL/sycl/backend/opencl.hpp b/sycl/include/CL/sycl/backend/opencl.hpp index abd406260eb80..81e6a2de4b62e 100644 --- a/sycl/include/CL/sycl/backend/opencl.hpp +++ b/sycl/include/CL/sycl/backend/opencl.hpp @@ -36,6 +36,8 @@ template <> struct interop { using type = cl_program; }; +template <> struct interop { using type = cl_event; }; + template struct interop get_devices(info::device_type deviceType = info::device_type::all); + /// Returns the backend associated with this device. + /// + /// \return the backend associated with this device. + backend get_backend() const noexcept; + /// Gets the native handle of the SYCL device. /// /// \return a native handle, the type of which defined by the backend. diff --git a/sycl/include/CL/sycl/event.hpp b/sycl/include/CL/sycl/event.hpp index 2b96d9e547faa..231044f0402f1 100644 --- a/sycl/include/CL/sycl/event.hpp +++ b/sycl/include/CL/sycl/event.hpp @@ -118,12 +118,18 @@ class __SYCL_EXPORT event { typename info::param_traits::return_type get_profiling_info() const; + /// Returns the backend associated with this platform. + /// + /// \return the backend associated with this platform + backend get_backend() const noexcept; + /// Gets the native handle of the SYCL event. /// /// \return a native handle, the type of which defined by the backend. template auto get_native() const -> typename interop::type { - return static_cast::type>(getNative()); + return reinterpret_cast::type>( + getNative()); } private: diff --git a/sycl/include/CL/sycl/program.hpp b/sycl/include/CL/sycl/program.hpp index e97c109ee9c61..f041c2f695fdc 100644 --- a/sycl/include/CL/sycl/program.hpp +++ b/sycl/include/CL/sycl/program.hpp @@ -356,6 +356,11 @@ class __SYCL_EXPORT program { #endif // __SYCL_DEVICE_ONLY__ } + /// Returns the backend associated with this program. + /// + /// \return the backend associated with this program. + backend get_backend() const noexcept; + /// Gets the native handle of the SYCL platform. /// /// \return a native handle, the type of which defined by the backend. diff --git a/sycl/include/CL/sycl/queue.hpp b/sycl/include/CL/sycl/queue.hpp index 5cca7be19772b..a1c49a05043be 100644 --- a/sycl/include/CL/sycl/queue.hpp +++ b/sycl/include/CL/sycl/queue.hpp @@ -750,6 +750,11 @@ class __SYCL_EXPORT queue { /// Equivalent to has_property() bool is_in_order() const; + /// Returns the backend associated with this queue. + /// + /// \return the backend associated with this queue. + backend get_backend() const noexcept; + /// Gets the native handle of the SYCL queue. /// /// \return a native handle, the type of which defined by the backend. diff --git a/sycl/source/context.cpp b/sycl/source/context.cpp index 5e30d0bd955f2..607a4edc44288 100644 --- a/sycl/source/context.cpp +++ b/sycl/source/context.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -117,6 +118,8 @@ cl_context context::get() const { return impl->get(); } bool context::is_host() const { return impl->is_host(); } +backend context::get_backend() const noexcept { return getImplBackend(impl); } + platform context::get_platform() const { return impl->get_info(); } diff --git a/sycl/source/detail/backend_impl.hpp b/sycl/source/detail/backend_impl.hpp new file mode 100644 index 0000000000000..f85c20c9cd6ef --- /dev/null +++ b/sycl/source/detail/backend_impl.hpp @@ -0,0 +1,29 @@ +//==------------------ backend_impl.hpp - get impls backend +//-------------------------==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#pragma once +#include + +__SYCL_INLINE_NAMESPACE(cl) { +namespace sycl { +namespace detail { + +template backend getImplBackend(const T &Impl) { + backend Result; + if (Impl->is_host()) + Result = backend::host; + else + Result = Impl->getPlugin().getBackend(); + + return Result; +} + +} // namespace detail +} // namespace sycl +} // __SYCL_INLINE_NAMESPACE(cl) diff --git a/sycl/source/detail/context_impl.cpp b/sycl/source/detail/context_impl.cpp index 3dbcc18d94fb3..f8a561a788ef5 100644 --- a/sycl/source/detail/context_impl.cpp +++ b/sycl/source/detail/context_impl.cpp @@ -169,6 +169,8 @@ bool context_impl::hasDevice( pi_native_handle context_impl::getNative() const { auto Plugin = getPlugin(); + if (Plugin.getBackend() == backend::opencl) + Plugin.call(getHandleRef()); pi_native_handle Handle; Plugin.call(getHandleRef(), &Handle); return Handle; diff --git a/sycl/source/detail/device_impl.cpp b/sycl/source/detail/device_impl.cpp index 7343954313c16..5e4c0c4b9d42e 100644 --- a/sycl/source/detail/device_impl.cpp +++ b/sycl/source/detail/device_impl.cpp @@ -209,6 +209,8 @@ vector_class device_impl::create_sub_devices( pi_native_handle device_impl::getNative() const { auto Plugin = getPlugin(); + if (Plugin.getBackend() == backend::opencl) + Plugin.call(getHandleRef()); pi_native_handle Handle; Plugin.call(getHandleRef(), &Handle); return Handle; diff --git a/sycl/source/detail/event_impl.cpp b/sycl/source/detail/event_impl.cpp index d034a259d136c..2f6ebadb68c05 100644 --- a/sycl/source/detail/event_impl.cpp +++ b/sycl/source/detail/event_impl.cpp @@ -292,6 +292,8 @@ void HostProfilingInfo::end() { EndTime = getTimestamp(); } pi_native_handle event_impl::getNative() const { auto Plugin = getPlugin(); + if (Plugin.getBackend() == backend::opencl) + Plugin.call(getHandleRef()); pi_native_handle Handle; Plugin.call(getHandleRef(), &Handle); return Handle; diff --git a/sycl/source/detail/event_impl.hpp b/sycl/source/detail/event_impl.hpp index 4b291159c8e4f..81e9e9b626356 100644 --- a/sycl/source/detail/event_impl.hpp +++ b/sycl/source/detail/event_impl.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include diff --git a/sycl/source/detail/platform_impl.hpp b/sycl/source/detail/platform_impl.hpp index a2a269ade0e96..2dea8751da14d 100644 --- a/sycl/source/detail/platform_impl.hpp +++ b/sycl/source/detail/platform_impl.hpp @@ -108,18 +108,6 @@ class platform_impl { /// \return a vector of all available SYCL platforms. static vector_class get_platforms(); - // \return the Backend associated with this platform. - backend get_backend() const noexcept { - backend Result; - if (is_host()) - Result = backend::host; - else { - Result = getPlugin().getBackend(); - } - - return Result; - } - // \return the Plugin associated with this platform. const plugin &getPlugin() const { assert(!MHostPlatform && "Plugin is not available for Host."); diff --git a/sycl/source/detail/program_impl.cpp b/sycl/source/detail/program_impl.cpp index 731787fa35943..634ce6e9d2d91 100644 --- a/sycl/source/detail/program_impl.cpp +++ b/sycl/source/detail/program_impl.cpp @@ -583,6 +583,8 @@ void program_impl::flush_spec_constants(const RTDeviceBinaryImage &Img, pi_native_handle program_impl::getNative() const { const auto &Plugin = getPlugin(); + if (Plugin.getBackend() == backend::opencl) + Plugin.call(MProgram); pi_native_handle Handle; Plugin.call(MProgram, &Handle); return Handle; diff --git a/sycl/source/detail/queue_impl.cpp b/sycl/source/detail/queue_impl.cpp index 9d4fe1bcc36d0..bcbe28720ac56 100644 --- a/sycl/source/detail/queue_impl.cpp +++ b/sycl/source/detail/queue_impl.cpp @@ -273,6 +273,8 @@ void queue_impl::initHostTaskAndEventCallbackThreadPool() { pi_native_handle queue_impl::getNative() const { const detail::plugin &Plugin = getPlugin(); + if (Plugin.getBackend() == backend::opencl) + Plugin.call(MQueues[0]); pi_native_handle Handle{}; Plugin.call(MQueues[0], &Handle); return Handle; diff --git a/sycl/source/device.cpp b/sycl/source/device.cpp index 57ca9f6190615..cc9e0f74ea5c7 100644 --- a/sycl/source/device.cpp +++ b/sycl/source/device.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -136,6 +137,8 @@ device::get_info() const { #undef __SYCL_PARAM_TRAITS_SPEC +backend device::get_backend() const noexcept { return getImplBackend(impl); } + pi_native_handle device::getNative() const { return impl->getNative(); } bool device::has(aspect Aspect) const { return impl->has(Aspect); } diff --git a/sycl/source/event.cpp b/sycl/source/event.cpp index fa36438ae09b5..c8b94a5644b13 100644 --- a/sycl/source/event.cpp +++ b/sycl/source/event.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -85,6 +86,8 @@ event::event(shared_ptr_class event_impl) #undef __SYCL_PARAM_TRAITS_SPEC +backend event::get_backend() const noexcept { return getImplBackend(impl); } + pi_native_handle event::getNative() const { return impl->getNative(); } } // namespace sycl diff --git a/sycl/source/platform.cpp b/sycl/source/platform.cpp index 3ab9f5b020d6d..a70a1b44d9179 100644 --- a/sycl/source/platform.cpp +++ b/sycl/source/platform.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -43,7 +44,7 @@ vector_class platform::get_platforms() { return detail::platform_impl::get_platforms(); } -backend platform::get_backend() const noexcept { return impl->get_backend(); } +backend platform::get_backend() const noexcept { return getImplBackend(impl); } template typename info::param_traits::return_type diff --git a/sycl/source/program.cpp b/sycl/source/program.cpp index c7a33d7ba8d1b..793c85954fcfc 100644 --- a/sycl/source/program.cpp +++ b/sycl/source/program.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -47,6 +48,8 @@ program::program(const context &context, cl_program clProgram) clRetainProgram(clProgram); } +backend program::get_backend() const noexcept { return getImplBackend(impl); } + pi_native_handle program::getNative() const { return impl->getNative(); } program::program(std::shared_ptr impl) : impl(impl) {} diff --git a/sycl/source/queue.cpp b/sycl/source/queue.cpp index a651d4a5d9236..e470a5c845d88 100644 --- a/sycl/source/queue.cpp +++ b/sycl/source/queue.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -138,6 +139,8 @@ bool queue::is_in_order() const { return impl->has_property(); } +backend queue::get_backend() const noexcept { return getImplBackend(impl); } + pi_native_handle queue::getNative() const { return impl->getNative(); } } // namespace sycl diff --git a/sycl/test/abi/sycl_symbols_linux.dump b/sycl/test/abi/sycl_symbols_linux.dump index eb9608569576c..3918605a1d2c4 100644 --- a/sycl/test/abi/sycl_symbols_linux.dump +++ b/sycl/test/abi/sycl_symbols_linux.dump @@ -3897,6 +3897,7 @@ _ZNK2cl4sycl15interop_handler12GetNativeMemEPNS0_6detail16AccessorImplHostE _ZNK2cl4sycl15interop_handler14GetNativeQueueEv _ZNK2cl4sycl16default_selectorclERKNS0_6deviceE _ZNK2cl4sycl20accelerator_selectorclERKNS0_6deviceE +_ZNK2cl4sycl5event11get_backendEv _ZNK2cl4sycl5event18get_profiling_infoILNS0_4info15event_profilingE4737EEENS3_12param_traitsIS4_XT_EE11return_typeEv _ZNK2cl4sycl5event18get_profiling_infoILNS0_4info15event_profilingE4738EEENS3_12param_traitsIS4_XT_EE11return_typeEv _ZNK2cl4sycl5event18get_profiling_infoILNS0_4info15event_profilingE4739EEENS3_12param_traitsIS4_XT_EE11return_typeEv @@ -3908,6 +3909,7 @@ _ZNK2cl4sycl5event9getNativeEv _ZNK2cl4sycl5eventeqERKS1_ _ZNK2cl4sycl5eventneERKS1_ _ZNK2cl4sycl5queue10get_deviceEv +_ZNK2cl4sycl5queue11get_backendEv _ZNK2cl4sycl5queue11get_contextEv _ZNK2cl4sycl5queue11is_in_orderEv _ZNK2cl4sycl5queue12get_propertyINS0_8property5queue16enable_profilingEEET_v @@ -3968,6 +3970,7 @@ _ZNK2cl4sycl6detail19kernel_bundle_plain37get_specialization_constant_raw_valueE _ZNK2cl4sycl6detail19kernel_bundle_plain3endEv _ZNK2cl4sycl6detail19kernel_bundle_plain5beginEv _ZNK2cl4sycl6detail19kernel_bundle_plain5emptyEv +_ZNK2cl4sycl6device11get_backendEv _ZNK2cl4sycl6device12get_platformEv _ZNK2cl4sycl6device13has_extensionERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE _ZNK2cl4sycl6device14is_acceleratorEv @@ -4103,6 +4106,7 @@ _ZNK2cl4sycl6stream22get_max_statement_sizeEv _ZNK2cl4sycl6stream8get_sizeEv _ZNK2cl4sycl6streameqERKS1_ _ZNK2cl4sycl6streamneERKS1_ +_ZNK2cl4sycl7context11get_backendEv _ZNK2cl4sycl7context11get_devicesEv _ZNK2cl4sycl7context12get_platformEv _ZNK2cl4sycl7context12get_propertyINS0_3ext6oneapi8property6buffer22use_pinned_host_memoryEEET_v @@ -4135,6 +4139,7 @@ _ZNK2cl4sycl7program10get_kernelENSt7__cxx1112basic_stringIcSt11char_traitsIcESa _ZNK2cl4sycl7program10get_kernelENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEb _ZNK2cl4sycl7program10has_kernelENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE _ZNK2cl4sycl7program10has_kernelENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEb +_ZNK2cl4sycl7program11get_backendEv _ZNK2cl4sycl7program11get_contextEv _ZNK2cl4sycl7program11get_devicesEv _ZNK2cl4sycl7program12get_binariesEv diff --git a/sycl/unittests/CMakeLists.txt b/sycl/unittests/CMakeLists.txt index 1d500283eed37..f2789b4ffb6a1 100644 --- a/sycl/unittests/CMakeLists.txt +++ b/sycl/unittests/CMakeLists.txt @@ -9,6 +9,7 @@ endforeach() include(AddSYCLUnitTest) +add_subdirectory(get_native_interop) add_subdirectory(misc) add_subdirectory(pi) add_subdirectory(kernel-and-program) diff --git a/sycl/unittests/get_native_interop/CMakeLists.txt b/sycl/unittests/get_native_interop/CMakeLists.txt new file mode 100644 index 0000000000000..b65136606d448 --- /dev/null +++ b/sycl/unittests/get_native_interop/CMakeLists.txt @@ -0,0 +1,3 @@ +add_sycl_unittest_with_device(GetNativeTests OBJECT + test_get_native.cpp +) diff --git a/sycl/unittests/get_native_interop/test_get_native.cpp b/sycl/unittests/get_native_interop/test_get_native.cpp new file mode 100644 index 0000000000000..0930011ff74e6 --- /dev/null +++ b/sycl/unittests/get_native_interop/test_get_native.cpp @@ -0,0 +1,133 @@ +//==----------- test_get_native.cpp --- get_native interop unit test only for +// opencl +//-------------==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include +#include +#include +#include +#include + +#include +#include + +using namespace cl::sycl; + +int TestCounter; + +static pi_result redefinedContextRetain(pi_context c) { + ++TestCounter; + return PI_SUCCESS; +} + +static pi_result redefinedQueueRetain(pi_queue c) { + ++TestCounter; + return PI_SUCCESS; +} + +static pi_result redefinedDeviceRetain(pi_device c) { + ++TestCounter; + return PI_SUCCESS; +} + +static pi_result redefinedProgramRetain(pi_program c) { + ++TestCounter; + return PI_SUCCESS; +} + +static pi_result redefinedEventRetain(pi_event c) { + ++TestCounter; + return PI_SUCCESS; +} + +static pi_result redefinedProgramCreateWithSource(pi_context context, + pi_uint32 count, + const char **strings, + const size_t *lengths, + pi_program *ret_program) { + return PI_SUCCESS; +} + +static pi_result +redefinedProgramBuild(pi_program program, pi_uint32 num_devices, + const pi_device *device_list, const char *options, + void (*pfn_notify)(pi_program program, void *user_data), + void *user_data) { + return PI_SUCCESS; +} + +pi_result redefinedEventsWait(pi_uint32 num_events, + const pi_event *event_list) { + return PI_SUCCESS; +} + +pi_result redefinedEventGetInfo(pi_event event, pi_event_info param_name, + size_t param_value_size, void *param_value, + size_t *param_value_size_ret) { + EXPECT_EQ(param_name, PI_EVENT_INFO_COMMAND_EXECUTION_STATUS) + << "Unexpected event info requested"; + // Report half of events as complete + static int Counter = 0; + auto *Result = reinterpret_cast(param_value); + *Result = (++Counter % 2 == 0) ? PI_EVENT_COMPLETE : PI_EVENT_RUNNING; + return PI_SUCCESS; +} + +pi_result redefinedEventRelease(pi_event event) { return PI_SUCCESS; } + +TEST(GetNativeTest, GetNativeHandle) { + platform Plt{default_selector()}; + if (Plt.get_backend() != backend::opencl) { + std::cout << "Test is created for opencl only" << std::endl; + return; + } + if (Plt.is_host()) { + std::cout << "Not run on host - no PI events created in that case" + << std::endl; + return; + } + TestCounter = 0; + + unittest::PiMock Mock{Plt}; + Mock.redefine( + redefinedProgramCreateWithSource); + Mock.redefine(redefinedProgramBuild); + + Mock.redefine(redefinedEventsWait); + Mock.redefine(redefinedEventGetInfo); + Mock.redefine(redefinedEventRelease); + + Mock.redefine(redefinedContextRetain); + Mock.redefine(redefinedQueueRetain); + Mock.redefine(redefinedDeviceRetain); + Mock.redefine(redefinedProgramRetain); + Mock.redefine(redefinedEventRetain); + + default_selector Selector; + context Context(Plt); + queue Queue(Context, Selector); + + program Program{Context}; + Program.build_with_source(""); + + auto Device = Queue.get_device(); + + unsigned char *HostAlloc = (unsigned char *)malloc_host(1, Context); + auto Event = Queue.memset(HostAlloc, 42, 1); + + auto c_g = get_native(Context); + auto q_g = get_native(Queue); + auto p_g = get_native(Program); + auto d_g = get_native(Device); + auto e_g = get_native(Event); + + // When creating a context, the piDeviceRetain is called so here is the 6 + // retain calls + ASSERT_EQ(TestCounter, 6) << "Not all the retain methods was called"; +}