aboutsummaryrefslogtreecommitdiff
path: root/src/venus/vkr_ring.h
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-05-10 07:06:44 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-05-10 07:06:44 +0000
commit00d361e7138fec6beeed6a18968d1aecf40e2b86 (patch)
tree053d3acaad91c69e7ad71b460a591612de7d19c3 /src/venus/vkr_ring.h
parent6f2f2cb306e21b32e9fe759dd206a5e2a2b312c0 (diff)
parent95be3cd08d582499c402ff79db4d4093b1b8c780 (diff)
downloadvirglrenderer-00d361e7138fec6beeed6a18968d1aecf40e2b86.tar.gz
Change-Id: I129b4e72d8b841253c02fc27ce45a85631227ffe
Diffstat (limited to 'src/venus/vkr_ring.h')
-rw-r--r--src/venus/vkr_ring.h126
1 files changed, 126 insertions, 0 deletions
diff --git a/src/venus/vkr_ring.h b/src/venus/vkr_ring.h
new file mode 100644
index 00000000..8dc83bb5
--- /dev/null
+++ b/src/venus/vkr_ring.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2021 Google LLC
+ * SPDX-License-Identifier: MIT
+ */
+
+#ifndef VKR_RING_H
+#define VKR_RING_H
+
+#include "vkr_common.h"
+
+/* We read from the ring buffer to a temporary buffer for
+ * virgl_context::submit_cmd. Until that is changed, we want to put a limit
+ * on the size of the temporary buffer. It also makes no sense to have huge
+ * rings.
+ *
+ * This must not exceed UINT32_MAX because the ring head and tail are 32-bit.
+ */
+#define VKR_RING_BUFFER_MAX_SIZE (16u * 1024 * 1024)
+
+/* The layout of a ring in a virgl_resource. This is parsed and discarded by
+ * vkr_ring_create.
+ */
+struct vkr_ring_layout {
+ struct virgl_resource *resource;
+
+ struct vkr_region head;
+ struct vkr_region tail;
+ struct vkr_region status;
+ struct vkr_region buffer;
+ struct vkr_region extra;
+};
+
+static_assert(ATOMIC_INT_LOCK_FREE == 2 && sizeof(atomic_uint) == 4,
+ "vkr_ring_control requires lock-free 32-bit atomic_uint");
+
+/* the control region of a ring */
+struct vkr_ring_control {
+ /* Pointers to ring head, tail, and status.
+ *
+ * Clients increment the tail after commands are added. We increment the
+ * head after commands are executed. The status is updated when there is a
+ * status change to the ring thread.
+ */
+ volatile atomic_uint *head;
+ const volatile atomic_uint *tail;
+ volatile atomic_uint *status;
+};
+
+/* the buffer region of a ring */
+struct vkr_ring_buffer {
+ /* the base of the region in the resource */
+ int base_iov_index;
+ size_t base_iov_offset;
+
+ uint32_t size;
+ uint32_t mask;
+
+ /* The current offset in the buffer region. It is free-running and must be
+ * masked to be between [0, size).
+ */
+ uint32_t cur;
+
+ /* The current iov and iov offset in the resource. */
+ const struct iovec *cur_iov;
+ int cur_iov_index;
+ size_t cur_iov_offset;
+};
+
+/* the extra region of a ring */
+struct vkr_ring_extra {
+ /* the base of the region in the resource */
+ int base_iov_index;
+ size_t base_iov_offset;
+
+ /* used for offset validation */
+ struct vkr_region region;
+
+ /* cache the latest offset->pointer result */
+ size_t cached_offset;
+ volatile atomic_uint *cached_data;
+};
+
+struct vkr_ring {
+ /* used by the caller */
+ vkr_object_id id;
+ struct list_head head;
+
+ /* ring regions */
+ struct virgl_resource *resource;
+ struct vkr_ring_control control;
+ struct vkr_ring_buffer buffer;
+ struct vkr_ring_extra extra;
+
+ /* ring thread */
+ struct virgl_context *context;
+ uint64_t idle_timeout;
+ void *cmd;
+
+ mtx_t mutex;
+ cnd_t cond;
+ thrd_t thread;
+ atomic_bool started;
+ atomic_bool pending_notify;
+};
+
+struct vkr_ring *
+vkr_ring_create(const struct vkr_ring_layout *layout,
+ struct virgl_context *ctx,
+ uint64_t idle_timeout);
+
+void
+vkr_ring_destroy(struct vkr_ring *ring);
+
+void
+vkr_ring_start(struct vkr_ring *ring);
+
+bool
+vkr_ring_stop(struct vkr_ring *ring);
+
+void
+vkr_ring_notify(struct vkr_ring *ring);
+
+bool
+vkr_ring_write_extra(struct vkr_ring *ring, size_t offset, uint32_t val);
+
+#endif /* VKR_RING_H */