[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 <kseniya.tikhomirova@intel.com>
This commit is contained in:
Kseniya Tikhomirova
2026-04-09 15:59:44 +02:00
committed by GitHub
parent 283a591545
commit ef31b272d2
11 changed files with 261 additions and 7 deletions

View File

@@ -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.

View File

@@ -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 <sycl/__impl/backend.hpp>
#include <sycl/__impl/detail/config.hpp>
#include <sycl/__impl/detail/obj_utils.hpp>
#include <sycl/__impl/info/desc_base.hpp>
#include <memory>
#include <vector>
_LIBSYCL_BEGIN_NAMESPACE_SYCL
class event;
namespace detail {
class EventImpl;
template <typename T>
using is_event_info_desc_t = typename is_info_desc<T, event>::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<event> &eventList);
/// Queries this SYCL event for information.
///
/// \return depends on the information being requested.
template <typename Param>
detail::is_event_info_desc_t<Param> get_info() const;
/// Queries this SYCL event for SYCL backend-specific information.
///
/// \return depends on the information being queried.
template <typename Param>
typename Param::return_type get_backend_info() const;
private:
event(std::shared_ptr<detail::EventImpl> Impl) : impl(Impl) {}
std::shared_ptr<detail::EventImpl> impl;
friend sycl::detail::ImplUtils;
};
_LIBSYCL_END_NAMESPACE_SYCL
template <>
struct std::hash<sycl::event> : public sycl::detail::HashBase<sycl::event> {};
#endif // _LIBSYCL___IMPL_EVENT_HPP

View File

@@ -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>
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<detail::QueueImpl> &Impl) : impl(Impl) {}
std::shared_ptr<detail::QueueImpl> impl;

View File

@@ -17,6 +17,7 @@
#include <sycl/__impl/context.hpp>
#include <sycl/__impl/device.hpp>
#include <sycl/__impl/device_selector.hpp>
#include <sycl/__impl/event.hpp>
#include <sycl/__impl/exception.hpp>
#include <sycl/__impl/platform.hpp>
#include <sycl/__impl/queue.hpp>

View File

@@ -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"

View File

@@ -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 <detail/event_impl.hpp>
#include <detail/platform_impl.hpp>
_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

View File

@@ -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 <sycl/__impl/backend.hpp>
#include <sycl/__impl/detail/config.hpp>
#include <OffloadAPI.h>
#include <memory>
_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<EventImpl>
createEventWithHandle(ol_event_handle_t Event, PlatformImpl &Platform) {
return std::make_shared<EventImpl>(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

View File

@@ -9,6 +9,7 @@
#include <detail/queue_impl.hpp>
#include <detail/device_impl.hpp>
#include <detail/event_impl.hpp>
_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

View File

@@ -27,6 +27,7 @@ namespace detail {
class ContextImpl;
class DeviceImpl;
class EventImpl;
class QueueImpl : public std::enable_shared_from_this<QueueImpl> {
struct PrivateTag {
@@ -34,7 +35,7 @@ class QueueImpl : public std::enable_shared_from_this<QueueImpl> {
};
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;

25
libsycl/src/event.cpp Normal file
View File

@@ -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 <sycl/__impl/event.hpp>
#include <detail/event_impl.hpp>
_LIBSYCL_BEGIN_NAMESPACE_SYCL
backend event::get_backend() const noexcept { return impl->getBackend(); }
void event::wait(const std::vector<event> &EventList) {
for (auto Event : EventList) {
Event.wait();
}
}
void event::wait() { impl->wait(); }
_LIBSYCL_END_NAMESPACE_SYCL

View File

@@ -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