From ef31b272d252f8c806f24fc95c41bd2507720c7d Mon Sep 17 00:00:00 2001 From: Kseniya Tikhomirova Date: Thu, 9 Apr 2026 15:59:44 +0200 Subject: [PATCH] [libsycl] add sycl::event and wait functionality to event & queue (#188793) Depends on https://github.com/llvm/llvm-project/pull/187528. This is part of the SYCL support upstreaming effort. The relevant RFCs can be found here: https://discourse.llvm.org/t/rfc-add-full-support-for-the-sycl-programming-model/74080 https://discourse.llvm.org/t/rfc-sycl-runtime-upstreaming/74479 --------- Signed-off-by: Tikhomirova, Kseniya --- libsycl/docs/index.rst | 11 +++- libsycl/include/sycl/__impl/event.hpp | 88 +++++++++++++++++++++++++++ libsycl/include/sycl/__impl/queue.hpp | 9 ++- libsycl/include/sycl/sycl.hpp | 1 + libsycl/src/CMakeLists.txt | 2 + libsycl/src/detail/event_impl.cpp | 36 +++++++++++ libsycl/src/detail/event_impl.hpp | 74 ++++++++++++++++++++++ libsycl/src/detail/queue_impl.cpp | 13 +++- libsycl/src/detail/queue_impl.hpp | 7 ++- libsycl/src/event.cpp | 25 ++++++++ libsycl/src/queue.cpp | 2 + 11 files changed, 261 insertions(+), 7 deletions(-) create mode 100644 libsycl/include/sycl/__impl/event.hpp create mode 100644 libsycl/src/detail/event_impl.cpp create mode 100644 libsycl/src/detail/event_impl.hpp create mode 100644 libsycl/src/event.cpp diff --git a/libsycl/docs/index.rst b/libsycl/docs/index.rst index 03f7fb7c0876..9aa36b4a54c5 100644 --- a/libsycl/docs/index.rst +++ b/libsycl/docs/index.rst @@ -106,7 +106,14 @@ TODO for added SYCL classes * device selection: to add compatibility with old SYCL 1.2.1 device selectors, still part of SYCL 2020 specification * ``context``: to implement get_info, properties & public constructors once context support is added to liboffload -* ``queue``: to implement USM methods, to implement synchronization methods, to implement submit & copy with accessors (low priority), get_info & properties, ctors that accepts context (blocked by lack of liboffload support) +* ``queue``: + + * to implement USM methods + * to implement synchronization methods + * to implement submit & copy with accessors (low priority) + * get_info & properties + * ctors that accepts context (blocked by lack of liboffload support) + * ``property_list``: to fully implement and integrate with existing SYCL runtime classes supporting it * usm allocations: @@ -114,7 +121,7 @@ TODO for added SYCL classes * forward templated funcs to alignment methods (rewrite current impl) * handle sub devices once they are implemented (blocked by liboffload support) - +* ``event``: get_wait_list, get_info, get_profiling_info, wait_and_throw & default ctor are not implemented * general opens: * define a way to report errors from object dtors. \ No newline at end of file diff --git a/libsycl/include/sycl/__impl/event.hpp b/libsycl/include/sycl/__impl/event.hpp new file mode 100644 index 000000000000..141b804621f2 --- /dev/null +++ b/libsycl/include/sycl/__impl/event.hpp @@ -0,0 +1,88 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file contains the declaration of the SYCL event class (SYCL +/// 2020 4.6.6.), that represents the status of an operation that is being +/// executed by the SYCL runtime. +/// +//===----------------------------------------------------------------------===// + +#ifndef _LIBSYCL___IMPL_EVENT_HPP +#define _LIBSYCL___IMPL_EVENT_HPP + +#include +#include +#include +#include + +#include +#include + +_LIBSYCL_BEGIN_NAMESPACE_SYCL + +class event; + +namespace detail { +class EventImpl; +template +using is_event_info_desc_t = typename is_info_desc::return_type; +} // namespace detail + +/// SYCL 2020 4.6.6. Event class. +class _LIBSYCL_EXPORT event { +public: + event(const event &rhs) = default; + event(event &&rhs) = default; + event &operator=(const event &rhs) = default; + event &operator=(event &&rhs) = default; + ~event() = default; + + friend bool operator==(const event &lhs, const event &rhs) { + return lhs.impl == rhs.impl; + } + + friend bool operator!=(const event &lhs, const event &rhs) { + return !(lhs == rhs); + } + + /// \return the backend associated with this event. + backend get_backend() const noexcept; + + /// Blocks until all commands associated with this event and any dependent + /// events have completed. + void wait(); + + /// Behaves as if calling event::wait on each event in eventList. + static void wait(const std::vector &eventList); + + /// Queries this SYCL event for information. + /// + /// \return depends on the information being requested. + template + detail::is_event_info_desc_t get_info() const; + + /// Queries this SYCL event for SYCL backend-specific information. + /// + /// \return depends on the information being queried. + template + typename Param::return_type get_backend_info() const; + +private: + event(std::shared_ptr Impl) : impl(Impl) {} + std::shared_ptr impl; + + friend sycl::detail::ImplUtils; +}; + +_LIBSYCL_END_NAMESPACE_SYCL + +template <> +struct std::hash : public sycl::detail::HashBase {}; + +#endif // _LIBSYCL___IMPL_EVENT_HPP diff --git a/libsycl/include/sycl/__impl/queue.hpp b/libsycl/include/sycl/__impl/queue.hpp index a440959c6311..41b018b681b8 100644 --- a/libsycl/include/sycl/__impl/queue.hpp +++ b/libsycl/include/sycl/__impl/queue.hpp @@ -35,12 +35,10 @@ class QueueImpl; class _LIBSYCL_EXPORT queue { public: queue(const queue &rhs) = default; - queue(queue &&rhs) = default; - queue &operator=(const queue &rhs) = default; - queue &operator=(queue &&rhs) = default; + ~queue() = default; friend bool operator==(const queue &lhs, const queue &rhs) { return lhs.impl == rhs.impl; @@ -136,6 +134,11 @@ public: template typename Param::return_type get_backend_info() const; + /// Blocks the calling thread until all commands previously submitted to this + /// queue have completed. Synchronous errors are reported through SYCL + /// exceptions. + void wait(); + private: queue(const std::shared_ptr &Impl) : impl(Impl) {} std::shared_ptr impl; diff --git a/libsycl/include/sycl/sycl.hpp b/libsycl/include/sycl/sycl.hpp index 3fcf088f4553..ce9fc8defd90 100644 --- a/libsycl/include/sycl/sycl.hpp +++ b/libsycl/include/sycl/sycl.hpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include diff --git a/libsycl/src/CMakeLists.txt b/libsycl/src/CMakeLists.txt index 4501005e433e..7b9826fb8a3d 100644 --- a/libsycl/src/CMakeLists.txt +++ b/libsycl/src/CMakeLists.txt @@ -85,6 +85,7 @@ endfunction(add_sycl_rt_library) set(LIBSYCL_SOURCES "context.cpp" + "event.cpp" "exception.cpp" "exception_list.cpp" "device.cpp" @@ -93,6 +94,7 @@ set(LIBSYCL_SOURCES "queue.cpp" "usm_functions.cpp" "detail/context_impl.cpp" + "detail/event_impl.cpp" "detail/device_impl.cpp" "detail/global_objects.cpp" "detail/platform_impl.cpp" diff --git a/libsycl/src/detail/event_impl.cpp b/libsycl/src/detail/event_impl.cpp new file mode 100644 index 000000000000..f4cee5675359 --- /dev/null +++ b/libsycl/src/detail/event_impl.cpp @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +_LIBSYCL_BEGIN_NAMESPACE_SYCL + +namespace detail { + +EventImpl::~EventImpl() { + if (MOffloadEvent) + std::ignore = olDestroyEvent(MOffloadEvent); +} + +backend EventImpl::getBackend() const noexcept { + // TODO: to handle default constructed. + return MPlatform.getBackend(); +} + +void EventImpl::wait() { + // MOffloadEvent == nullptr when the event is default constructed. Default + // constructed event is immediately completed. + if (!MOffloadEvent) + return; + + callAndThrow(olSyncEvent, MOffloadEvent); +} + +} // namespace detail +_LIBSYCL_END_NAMESPACE_SYCL diff --git a/libsycl/src/detail/event_impl.hpp b/libsycl/src/detail/event_impl.hpp new file mode 100644 index 000000000000..235bdb83f068 --- /dev/null +++ b/libsycl/src/detail/event_impl.hpp @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file contains the declaration of the EventImpl class, which +/// implements sycl::event functionality. +/// +//===----------------------------------------------------------------------===// + +#ifndef _LIBSYCL_EVENT_IMPL +#define _LIBSYCL_EVENT_IMPL + +#include +#include + +#include + +#include + +_LIBSYCL_BEGIN_NAMESPACE_SYCL +namespace detail { + +class PlatformImpl; + +class EventImpl { + // Helper to limit EventImpl creation. + struct PrivateTag { + explicit PrivateTag() = default; + }; + +public: + /// Constructs a SYCL event instance using the provided + /// offload event instance. + /// + /// \param Event is the raw offload library handle representing the event. + /// \param Platform is the platform this event belongs to. + EventImpl(ol_event_handle_t Event, PlatformImpl &Platform, PrivateTag) + : MOffloadEvent(Event), MPlatform(Platform) {} + + static std::shared_ptr + createEventWithHandle(ol_event_handle_t Event, PlatformImpl &Platform) { + return std::make_shared(Event, Platform, PrivateTag{}); + } + + /// Releases the handle to the corresponding liboffload event. + ~EventImpl(); + + /// \return the sycl::backend associated with this event. + backend getBackend() const noexcept; + + /// Waits for completion of the corresponding command and its dependencies. + void wait(); + + /// \return the liboffload handle that this SYCL event represents. + ol_event_handle_t getHandle() { return MOffloadEvent; } + + /// \return the platform implementation object this event belongs to. + const PlatformImpl &getPlatformImpl() const { return MPlatform; } + +private: + ol_event_handle_t MOffloadEvent{}; + PlatformImpl &MPlatform; +}; + +} // namespace detail + +_LIBSYCL_END_NAMESPACE_SYCL + +#endif // _LIBSYCL_EVENT_IMPL diff --git a/libsycl/src/detail/queue_impl.cpp b/libsycl/src/detail/queue_impl.cpp index 9c93fe02de8a..1d378f0ab5ef 100644 --- a/libsycl/src/detail/queue_impl.cpp +++ b/libsycl/src/detail/queue_impl.cpp @@ -9,6 +9,7 @@ #include #include +#include _LIBSYCL_BEGIN_NAMESPACE_SYCL @@ -18,9 +19,19 @@ QueueImpl::QueueImpl(DeviceImpl &deviceImpl, const async_handler &asyncHandler, const property_list &propList, PrivateTag) : MIsInorder(false), MAsyncHandler(asyncHandler), MPropList(propList), MDevice(deviceImpl), - MContext(MDevice.getPlatformImpl().getDefaultContext()) {} + MContext(MDevice.getPlatformImpl().getDefaultContext()) { + callAndThrow(olCreateQueue, MDevice.getOLHandle(), &MOffloadQueue); +} + +QueueImpl::~QueueImpl() { + // TODO: consider where to report errors + if (MOffloadQueue) + std::ignore = olDestroyQueue(MOffloadQueue); +} backend QueueImpl::getBackend() const noexcept { return MDevice.getBackend(); } +void QueueImpl::wait() { callAndThrow(olSyncQueue, MOffloadQueue); } + } // namespace detail _LIBSYCL_END_NAMESPACE_SYCL diff --git a/libsycl/src/detail/queue_impl.hpp b/libsycl/src/detail/queue_impl.hpp index 8882171181a6..047cb121150f 100644 --- a/libsycl/src/detail/queue_impl.hpp +++ b/libsycl/src/detail/queue_impl.hpp @@ -27,6 +27,7 @@ namespace detail { class ContextImpl; class DeviceImpl; +class EventImpl; class QueueImpl : public std::enable_shared_from_this { struct PrivateTag { @@ -34,7 +35,7 @@ class QueueImpl : public std::enable_shared_from_this { }; public: - ~QueueImpl() = default; + ~QueueImpl(); /// Constructs a SYCL queue from a device using an asyncHandler and /// a propList. @@ -65,7 +66,11 @@ public: /// \return true if and only if the queue is in order. bool isInOrder() const { return MIsInorder; } + /// Waits for completion of all commands submitted to this queue. + void wait(); + private: + ol_queue_handle_t MOffloadQueue = {}; const bool MIsInorder; const async_handler MAsyncHandler; const property_list MPropList; diff --git a/libsycl/src/event.cpp b/libsycl/src/event.cpp new file mode 100644 index 000000000000..c0276b519f17 --- /dev/null +++ b/libsycl/src/event.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +_LIBSYCL_BEGIN_NAMESPACE_SYCL + +backend event::get_backend() const noexcept { return impl->getBackend(); } + +void event::wait(const std::vector &EventList) { + for (auto Event : EventList) { + Event.wait(); + } +} + +void event::wait() { impl->wait(); } + +_LIBSYCL_END_NAMESPACE_SYCL diff --git a/libsycl/src/queue.cpp b/libsycl/src/queue.cpp index faed27467444..6584a6e080ec 100644 --- a/libsycl/src/queue.cpp +++ b/libsycl/src/queue.cpp @@ -33,4 +33,6 @@ device queue::get_device() const { bool queue::is_in_order() const { return impl->isInOrder(); } +void queue::wait() { impl->wait(); } + _LIBSYCL_END_NAMESPACE_SYCL