diff options
| author | PancakeTAS <pancake@mgnet.work> | 2026-05-18 11:21:25 +0200 |
|---|---|---|
| committer | PancakeTAS <pancake@mgnet.work> | 2026-05-18 11:21:25 +0200 |
| commit | ee13963e4088ebe7164f8a51bf97bc0f8b5e0af1 (patch) | |
| tree | c13996a27cd9105f89cc7de78bfdc77f3f8b0a10 /src/syncobject.cpp | |
| parent | Implement (non-timeline) sync objects (diff) | |
Extend sync objects with timeline support
Diffstat (limited to '')
| -rw-r--r-- | src/syncobject.cpp | 103 |
1 files changed, 94 insertions, 9 deletions
diff --git a/src/syncobject.cpp b/src/syncobject.cpp index 59c06fd..8d5e8b5 100644 --- a/src/syncobject.cpp +++ b/src/syncobject.cpp @@ -5,6 +5,7 @@ #include <cstdint> #include <optional> +#include <stdexcept> #include <vector> #include <unistd.h> @@ -50,12 +51,13 @@ int SyncObject::exportFd() const { return args.fd; } -void SyncObject::importSyncFile(int syncfile_fd, bool close) const { +void SyncObject::importSyncFile(int syncfile_fd, uint64_t point, bool close) const { try { drm_syncobj_handle args{ .handle = this->m_handle, .flags = DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE, - .fd = syncfile_fd + .fd = syncfile_fd, + .point = point }; ioctl::perform(this->m_fd, DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, args); } catch (...) { @@ -71,26 +73,64 @@ void SyncObject::importSyncFile(int syncfile_fd, bool close) const { } } -int SyncObject::exportSyncFile() const { +int SyncObject::exportSyncFile(uint64_t point) const { drm_syncobj_handle args{ .handle = this->m_handle, - .flags = DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE + .flags = DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE, + .point = point }; ioctl::perform(this->m_fd, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, args); return args.fd; } -void SyncObject::signal(int fd, const std::vector<uint32_t>& objects) { +void SyncObject::registerEventFd(int eventfd_fd, uint64_t point, bool waitAvailable) const { + drm_syncobj_eventfd args{ + .handle = this->m_handle, + .flags = waitAvailable ? DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE : 0U, + .point = point, + .fd = eventfd_fd + }; + ioctl::perform(this->m_fd, DRM_IOCTL_SYNCOBJ_EVENTFD, args); +} + +void SyncObject::transfer(uint32_t dstObject, uint64_t srcPoint, uint64_t dstPoint) const { + drm_syncobj_transfer args{ + .src_handle = this->m_handle, + .dst_handle = dstObject, + .src_point = srcPoint, + .dst_point = dstPoint + }; + ioctl::perform(this->m_fd, DRM_IOCTL_SYNCOBJ_TRANSFER, args); +} + +void SyncObject::signal( + int fd, + const std::vector<uint32_t>& objects, + const std::vector<uint64_t>& points +) { if (objects.empty()) { return; } - drm_syncobj_array args{ + if (points.empty()) { + drm_syncobj_array args{ + .handles = reinterpret_cast<uint64_t>(objects.data()), + .count_handles = static_cast<uint32_t>(objects.size()) + }; + ioctl::perform(fd, DRM_IOCTL_SYNCOBJ_SIGNAL, args); + } + + if (points.size() != objects.size()) { + throw std::invalid_argument("points size must match objects size"); + } + + drm_syncobj_timeline_array args{ .handles = reinterpret_cast<uint64_t>(objects.data()), + .points = reinterpret_cast<uint64_t>(points.data()), .count_handles = static_cast<uint32_t>(objects.size()) }; - ioctl::perform(fd, DRM_IOCTL_SYNCOBJ_SIGNAL, args); + ioctl::perform(fd, DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL, args); } void SyncObject::reset(int fd, const std::vector<uint32_t>& objects) { @@ -108,6 +148,7 @@ void SyncObject::reset(int fd, const std::vector<uint32_t>& objects) { uint32_t SyncObject::wait( int fd, const std::vector<uint32_t>& objects, + const std::vector<uint64_t>& points, int64_t timeout, bool waitAll, bool waitEmpty, @@ -122,8 +163,30 @@ uint32_t SyncObject::wait( waitEmpty = false; } - drm_syncobj_wait args{ + if (points.empty()) { + drm_syncobj_wait args{ + .handles = reinterpret_cast<uint64_t>(objects.data()), + .timeout_nsec = timeout, + .count_handles = static_cast<uint32_t>(objects.size()), + .flags = + (waitAll ? DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL : 0U) | + (waitEmpty ? DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT : 0U) | + (waitAvailable ? DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE : 0U) | + (deadlineHint.has_value() ? DRM_SYNCOBJ_WAIT_FLAGS_WAIT_DEADLINE : 0U), + .deadline_nsec = deadlineHint.value_or(0) + }; + ioctl::perform(fd, DRM_IOCTL_SYNCOBJ_WAIT, args); + + return args.first_signaled; + } + + if (points.size() != objects.size()) { + throw std::invalid_argument("points size must match objects size"); + } + + drm_syncobj_timeline_wait args{ .handles = reinterpret_cast<uint64_t>(objects.data()), + .points = reinterpret_cast<uint64_t>(points.data()), .timeout_nsec = timeout, .count_handles = static_cast<uint32_t>(objects.size()), .flags = @@ -133,11 +196,33 @@ uint32_t SyncObject::wait( (deadlineHint.has_value() ? DRM_SYNCOBJ_WAIT_FLAGS_WAIT_DEADLINE : 0U), .deadline_nsec = deadlineHint.value_or(0) }; - ioctl::perform(fd, DRM_IOCTL_SYNCOBJ_WAIT, args); + ioctl::perform(fd, DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT, args); return args.first_signaled; } +std::vector<uint64_t> SyncObject::query( + int fd, + const std::vector<uint32_t>& objects, + bool lastSubmitted +) { + if (objects.empty()) { + return {}; + } + + std::vector<uint64_t> points(objects.size()); + + drm_syncobj_timeline_array args{ + .handles = reinterpret_cast<uint64_t>(objects.data()), + .points = reinterpret_cast<uint64_t>(points.data()), + .count_handles = static_cast<uint32_t>(objects.size()), + .flags = lastSubmitted ? DRM_SYNCOBJ_QUERY_FLAGS_LAST_SUBMITTED : 0U + }; + ioctl::perform(fd, DRM_IOCTL_SYNCOBJ_QUERY, args); + + return points; +} + void SyncObject::destruct() noexcept { if (this->m_fd < 0) { return; |
