xref: /aosp_15_r20/external/mesa3d/src/virtio/vulkan/vn_ring.h (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright 2021 Google LLC
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #ifndef VN_RING_H
7 #define VN_RING_H
8 
9 #include "vn_common.h"
10 
11 #include "vn_cs.h"
12 
13 /**
14  * A ring is a single-producer and single-consumer circular buffer.  The data
15  * in the buffer are produced and consumed in order.  An externally-defined
16  * mechanism is required for ring setup and notifications in both directions.
17  * Notifications for new data from the producer are needed only when the
18  * consumer is not actively polling, which is indicated by the ring status.
19  *
20  * For venus, the data are plain venus commands.  When a venus command is
21  * consumed from the ring's perspective, there can still be ongoing CPU and/or
22  * GPU works.  This is not an issue when the works generated by following
23  * venus commands are correctly queued after the ongoing works.  There are
24  * also venus commands that facilitate polling or waiting for ongoing works.
25  */
26 
27 /* the layout of a ring in a shmem */
28 struct vn_ring_layout {
29    size_t head_offset;
30    size_t tail_offset;
31    size_t status_offset;
32 
33    size_t buffer_offset;
34    size_t buffer_size;
35 
36    size_t extra_offset;
37    size_t extra_size;
38 
39    size_t shmem_size;
40 };
41 
42 void
43 vn_ring_get_layout(size_t buf_size,
44                    size_t extra_size,
45                    struct vn_ring_layout *layout);
46 
47 struct vn_ring *
48 vn_ring_create(struct vn_instance *instance,
49                const struct vn_ring_layout *layout,
50                uint8_t direct_order,
51                bool is_tls_ring);
52 
53 void
54 vn_ring_destroy(struct vn_ring *ring);
55 
56 uint64_t
57 vn_ring_get_id(struct vn_ring *ring);
58 
59 uint32_t
60 vn_ring_load_status(const struct vn_ring *ring);
61 
62 void
63 vn_ring_unset_status_bits(struct vn_ring *ring, uint32_t mask);
64 
65 bool
66 vn_ring_get_seqno_status(struct vn_ring *ring, uint32_t seqno);
67 
68 void
69 vn_ring_wait_all(struct vn_ring *ring);
70 
71 struct vn_ring_submit_command {
72    /* empty command implies errors */
73    struct vn_cs_encoder command;
74    struct vn_cs_encoder_buffer buffer;
75    /* non-zero implies waiting */
76    size_t reply_size;
77 
78    /* when reply_size is non-zero, NULL can be returned on errors */
79    struct vn_renderer_shmem *reply_shmem;
80    struct vn_cs_decoder reply;
81 
82    /* valid when ring submission succeeds */
83    bool ring_seqno_valid;
84    uint32_t ring_seqno;
85 };
86 
87 static inline struct vn_cs_encoder *
vn_ring_submit_command_init(struct vn_ring * ring,struct vn_ring_submit_command * submit,void * cmd_data,size_t cmd_size,size_t reply_size)88 vn_ring_submit_command_init(struct vn_ring *ring,
89                             struct vn_ring_submit_command *submit,
90                             void *cmd_data,
91                             size_t cmd_size,
92                             size_t reply_size)
93 {
94    submit->buffer = VN_CS_ENCODER_BUFFER_INITIALIZER(cmd_data);
95    submit->command = VN_CS_ENCODER_INITIALIZER(&submit->buffer, cmd_size);
96 
97    submit->reply_size = reply_size;
98    submit->reply_shmem = NULL;
99 
100    submit->ring_seqno_valid = false;
101 
102    return &submit->command;
103 }
104 
105 static inline struct vn_cs_decoder *
vn_ring_get_command_reply(struct vn_ring * ring,struct vn_ring_submit_command * submit)106 vn_ring_get_command_reply(struct vn_ring *ring,
107                           struct vn_ring_submit_command *submit)
108 {
109    return submit->reply_shmem ? &submit->reply : NULL;
110 }
111 
112 void
113 vn_ring_free_command_reply(struct vn_ring *ring,
114                            struct vn_ring_submit_command *submit);
115 
116 void
117 vn_ring_submit_command(struct vn_ring *ring,
118                        struct vn_ring_submit_command *submit);
119 
120 VkResult
121 vn_ring_submit_command_simple(struct vn_ring *ring,
122                               const struct vn_cs_encoder *cs);
123 
124 VkResult
125 vn_ring_submit_roundtrip(struct vn_ring *ring, uint64_t *roundtrip_seqno);
126 
127 void
128 vn_ring_wait_roundtrip(struct vn_ring *ring, uint64_t roundtrip_seqno);
129 
130 static inline void
vn_ring_roundtrip(struct vn_ring * ring)131 vn_ring_roundtrip(struct vn_ring *ring)
132 {
133    uint64_t roundtrip_seqno;
134    if (vn_ring_submit_roundtrip(ring, &roundtrip_seqno) == VK_SUCCESS)
135       vn_ring_wait_roundtrip(ring, roundtrip_seqno);
136 }
137 
138 #endif /* VN_RING_H */
139