summaryrefslogtreecommitdiff
path: root/src/syncobject.cpp
diff options
context:
space:
mode:
authorPancakeTAS <pancake@mgnet.work>2026-05-18 11:21:25 +0200
committerPancakeTAS <pancake@mgnet.work>2026-05-18 11:21:25 +0200
commitee13963e4088ebe7164f8a51bf97bc0f8b5e0af1 (patch)
treec13996a27cd9105f89cc7de78bfdc77f3f8b0a10 /src/syncobject.cpp
parentImplement (non-timeline) sync objects (diff)
Extend sync objects with timeline support
Diffstat (limited to '')
-rw-r--r--src/syncobject.cpp103
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;