xref: /aosp_15_r20/external/virglrenderer/src/venus/vkr_ring.h (revision bbecb9d118dfdb95f99bd754f8fa9be01f189df3)
1*bbecb9d1SAndroid Build Coastguard Worker /*
2*bbecb9d1SAndroid Build Coastguard Worker  * Copyright 2021 Google LLC
3*bbecb9d1SAndroid Build Coastguard Worker  * SPDX-License-Identifier: MIT
4*bbecb9d1SAndroid Build Coastguard Worker  */
5*bbecb9d1SAndroid Build Coastguard Worker 
6*bbecb9d1SAndroid Build Coastguard Worker #ifndef VKR_RING_H
7*bbecb9d1SAndroid Build Coastguard Worker #define VKR_RING_H
8*bbecb9d1SAndroid Build Coastguard Worker 
9*bbecb9d1SAndroid Build Coastguard Worker #include "vkr_common.h"
10*bbecb9d1SAndroid Build Coastguard Worker 
11*bbecb9d1SAndroid Build Coastguard Worker /* We read from the ring buffer to a temporary buffer for
12*bbecb9d1SAndroid Build Coastguard Worker  * virgl_context::submit_cmd.  Until that is changed, we want to put a limit
13*bbecb9d1SAndroid Build Coastguard Worker  * on the size of the temporary buffer.  It also makes no sense to have huge
14*bbecb9d1SAndroid Build Coastguard Worker  * rings.
15*bbecb9d1SAndroid Build Coastguard Worker  *
16*bbecb9d1SAndroid Build Coastguard Worker  * This must not exceed UINT32_MAX because the ring head and tail are 32-bit.
17*bbecb9d1SAndroid Build Coastguard Worker  */
18*bbecb9d1SAndroid Build Coastguard Worker #define VKR_RING_BUFFER_MAX_SIZE (16u * 1024 * 1024)
19*bbecb9d1SAndroid Build Coastguard Worker 
20*bbecb9d1SAndroid Build Coastguard Worker /* The layout of a ring in a virgl_resource.  This is parsed and discarded by
21*bbecb9d1SAndroid Build Coastguard Worker  * vkr_ring_create.
22*bbecb9d1SAndroid Build Coastguard Worker  */
23*bbecb9d1SAndroid Build Coastguard Worker struct vkr_ring_layout {
24*bbecb9d1SAndroid Build Coastguard Worker    const struct vkr_resource_attachment *attachment;
25*bbecb9d1SAndroid Build Coastguard Worker 
26*bbecb9d1SAndroid Build Coastguard Worker    struct vkr_region head;
27*bbecb9d1SAndroid Build Coastguard Worker    struct vkr_region tail;
28*bbecb9d1SAndroid Build Coastguard Worker    struct vkr_region status;
29*bbecb9d1SAndroid Build Coastguard Worker    struct vkr_region buffer;
30*bbecb9d1SAndroid Build Coastguard Worker    struct vkr_region extra;
31*bbecb9d1SAndroid Build Coastguard Worker };
32*bbecb9d1SAndroid Build Coastguard Worker 
33*bbecb9d1SAndroid Build Coastguard Worker static_assert(ATOMIC_INT_LOCK_FREE == 2 && sizeof(atomic_uint) == 4,
34*bbecb9d1SAndroid Build Coastguard Worker               "vkr_ring_control requires lock-free 32-bit atomic_uint");
35*bbecb9d1SAndroid Build Coastguard Worker 
36*bbecb9d1SAndroid Build Coastguard Worker /* the control region of a ring */
37*bbecb9d1SAndroid Build Coastguard Worker struct vkr_ring_control {
38*bbecb9d1SAndroid Build Coastguard Worker    /* Pointers to ring head, tail, and status.
39*bbecb9d1SAndroid Build Coastguard Worker     *
40*bbecb9d1SAndroid Build Coastguard Worker     * Clients increment the tail after commands are added.  We increment the
41*bbecb9d1SAndroid Build Coastguard Worker     * head after commands are executed.  The status is updated when there is a
42*bbecb9d1SAndroid Build Coastguard Worker     * status change to the ring thread.
43*bbecb9d1SAndroid Build Coastguard Worker     */
44*bbecb9d1SAndroid Build Coastguard Worker    volatile atomic_uint *head;
45*bbecb9d1SAndroid Build Coastguard Worker    const volatile atomic_uint *tail;
46*bbecb9d1SAndroid Build Coastguard Worker    volatile atomic_uint *status;
47*bbecb9d1SAndroid Build Coastguard Worker };
48*bbecb9d1SAndroid Build Coastguard Worker 
49*bbecb9d1SAndroid Build Coastguard Worker /* the buffer region of a ring */
50*bbecb9d1SAndroid Build Coastguard Worker struct vkr_ring_buffer {
51*bbecb9d1SAndroid Build Coastguard Worker    /* the base of the region in the resource */
52*bbecb9d1SAndroid Build Coastguard Worker    int base_iov_index;
53*bbecb9d1SAndroid Build Coastguard Worker    size_t base_iov_offset;
54*bbecb9d1SAndroid Build Coastguard Worker 
55*bbecb9d1SAndroid Build Coastguard Worker    uint32_t size;
56*bbecb9d1SAndroid Build Coastguard Worker    uint32_t mask;
57*bbecb9d1SAndroid Build Coastguard Worker 
58*bbecb9d1SAndroid Build Coastguard Worker    /* The current offset in the buffer region.  It is free-running and must be
59*bbecb9d1SAndroid Build Coastguard Worker     * masked to be between [0, size).
60*bbecb9d1SAndroid Build Coastguard Worker     */
61*bbecb9d1SAndroid Build Coastguard Worker    uint32_t cur;
62*bbecb9d1SAndroid Build Coastguard Worker 
63*bbecb9d1SAndroid Build Coastguard Worker    /* The current iov and iov offset in the resource. */
64*bbecb9d1SAndroid Build Coastguard Worker    const struct iovec *cur_iov;
65*bbecb9d1SAndroid Build Coastguard Worker    int cur_iov_index;
66*bbecb9d1SAndroid Build Coastguard Worker    size_t cur_iov_offset;
67*bbecb9d1SAndroid Build Coastguard Worker };
68*bbecb9d1SAndroid Build Coastguard Worker 
69*bbecb9d1SAndroid Build Coastguard Worker /* the extra region of a ring */
70*bbecb9d1SAndroid Build Coastguard Worker struct vkr_ring_extra {
71*bbecb9d1SAndroid Build Coastguard Worker    /* the base of the region in the resource */
72*bbecb9d1SAndroid Build Coastguard Worker    int base_iov_index;
73*bbecb9d1SAndroid Build Coastguard Worker    size_t base_iov_offset;
74*bbecb9d1SAndroid Build Coastguard Worker 
75*bbecb9d1SAndroid Build Coastguard Worker    /* used for offset validation */
76*bbecb9d1SAndroid Build Coastguard Worker    struct vkr_region region;
77*bbecb9d1SAndroid Build Coastguard Worker 
78*bbecb9d1SAndroid Build Coastguard Worker    /* cache the latest offset->pointer result */
79*bbecb9d1SAndroid Build Coastguard Worker    size_t cached_offset;
80*bbecb9d1SAndroid Build Coastguard Worker    volatile atomic_uint *cached_data;
81*bbecb9d1SAndroid Build Coastguard Worker };
82*bbecb9d1SAndroid Build Coastguard Worker 
83*bbecb9d1SAndroid Build Coastguard Worker struct vkr_ring {
84*bbecb9d1SAndroid Build Coastguard Worker    /* used by the caller */
85*bbecb9d1SAndroid Build Coastguard Worker    vkr_object_id id;
86*bbecb9d1SAndroid Build Coastguard Worker    struct list_head head;
87*bbecb9d1SAndroid Build Coastguard Worker 
88*bbecb9d1SAndroid Build Coastguard Worker    /* ring regions */
89*bbecb9d1SAndroid Build Coastguard Worker    const struct vkr_resource_attachment *attachment;
90*bbecb9d1SAndroid Build Coastguard Worker    struct vkr_ring_control control;
91*bbecb9d1SAndroid Build Coastguard Worker    struct vkr_ring_buffer buffer;
92*bbecb9d1SAndroid Build Coastguard Worker    struct vkr_ring_extra extra;
93*bbecb9d1SAndroid Build Coastguard Worker 
94*bbecb9d1SAndroid Build Coastguard Worker    /* ring thread */
95*bbecb9d1SAndroid Build Coastguard Worker    struct virgl_context *context;
96*bbecb9d1SAndroid Build Coastguard Worker    uint64_t idle_timeout;
97*bbecb9d1SAndroid Build Coastguard Worker    void *cmd;
98*bbecb9d1SAndroid Build Coastguard Worker 
99*bbecb9d1SAndroid Build Coastguard Worker    mtx_t mutex;
100*bbecb9d1SAndroid Build Coastguard Worker    cnd_t cond;
101*bbecb9d1SAndroid Build Coastguard Worker    thrd_t thread;
102*bbecb9d1SAndroid Build Coastguard Worker    atomic_bool started;
103*bbecb9d1SAndroid Build Coastguard Worker    atomic_bool pending_notify;
104*bbecb9d1SAndroid Build Coastguard Worker };
105*bbecb9d1SAndroid Build Coastguard Worker 
106*bbecb9d1SAndroid Build Coastguard Worker struct vkr_ring *
107*bbecb9d1SAndroid Build Coastguard Worker vkr_ring_create(const struct vkr_ring_layout *layout,
108*bbecb9d1SAndroid Build Coastguard Worker                 struct virgl_context *ctx,
109*bbecb9d1SAndroid Build Coastguard Worker                 uint64_t idle_timeout);
110*bbecb9d1SAndroid Build Coastguard Worker 
111*bbecb9d1SAndroid Build Coastguard Worker void
112*bbecb9d1SAndroid Build Coastguard Worker vkr_ring_destroy(struct vkr_ring *ring);
113*bbecb9d1SAndroid Build Coastguard Worker 
114*bbecb9d1SAndroid Build Coastguard Worker void
115*bbecb9d1SAndroid Build Coastguard Worker vkr_ring_start(struct vkr_ring *ring);
116*bbecb9d1SAndroid Build Coastguard Worker 
117*bbecb9d1SAndroid Build Coastguard Worker bool
118*bbecb9d1SAndroid Build Coastguard Worker vkr_ring_stop(struct vkr_ring *ring);
119*bbecb9d1SAndroid Build Coastguard Worker 
120*bbecb9d1SAndroid Build Coastguard Worker void
121*bbecb9d1SAndroid Build Coastguard Worker vkr_ring_notify(struct vkr_ring *ring);
122*bbecb9d1SAndroid Build Coastguard Worker 
123*bbecb9d1SAndroid Build Coastguard Worker bool
124*bbecb9d1SAndroid Build Coastguard Worker vkr_ring_write_extra(struct vkr_ring *ring, size_t offset, uint32_t val);
125*bbecb9d1SAndroid Build Coastguard Worker 
126*bbecb9d1SAndroid Build Coastguard Worker #endif /* VKR_RING_H */
127