xref: /third_party/mesa3d/src/virtio/vulkan/vn_cs.h (revision bf215546)
1/*
2 * Copyright 2019 Google LLC
3 * SPDX-License-Identifier: MIT
4 */
5
6#ifndef VN_CS_H
7#define VN_CS_H
8
9#include "vn_common.h"
10
11#include "venus-protocol/vn_protocol_driver_info.h"
12
13#define VN_CS_ENCODER_BUFFER_INITIALIZER(storage)                            \
14   (struct vn_cs_encoder_buffer) { .base = storage, }
15
16/* note that buffers points to an unamed local variable */
17#define VN_CS_ENCODER_INITIALIZER_LOCAL(storage, size)                       \
18   (struct vn_cs_encoder)                                                    \
19   {                                                                         \
20      .storage_type = VN_CS_ENCODER_STORAGE_POINTER,                         \
21      .buffers = &VN_CS_ENCODER_BUFFER_INITIALIZER(storage),                 \
22      .buffer_count = 1, .buffer_max = 1, .current_buffer_size = size,       \
23      .cur = storage, .end = (const void *)(storage) + (size),               \
24   }
25
26#define VN_CS_ENCODER_INITIALIZER(buf, size)                                 \
27   (struct vn_cs_encoder)                                                    \
28   {                                                                         \
29      .storage_type = VN_CS_ENCODER_STORAGE_POINTER, .buffers = (buf),       \
30      .buffer_count = 1, .buffer_max = 1, .current_buffer_size = size,       \
31      .cur = (buf)->base, .end = (buf)->base + (size),                       \
32   }
33
34#define VN_CS_DECODER_INITIALIZER(storage, size)                             \
35   (struct vn_cs_decoder)                                                    \
36   {                                                                         \
37      .cur = storage, .end = (const void *)(storage) + (size),               \
38   }
39
40enum vn_cs_encoder_storage_type {
41   /* a pointer to an externally-managed storage */
42   VN_CS_ENCODER_STORAGE_POINTER,
43   /* an array of dynamically allocated shmems */
44   VN_CS_ENCODER_STORAGE_SHMEM_ARRAY,
45   /* same as above, but shmems are suballocated from a pool */
46   VN_CS_ENCODER_STORAGE_SHMEM_POOL,
47};
48
49struct vn_cs_encoder_buffer {
50   struct vn_renderer_shmem *shmem;
51   size_t offset;
52   void *base;
53   size_t committed_size;
54};
55
56struct vn_cs_encoder {
57   struct vn_instance *instance; /* TODO shmem cache */
58   enum vn_cs_encoder_storage_type storage_type;
59   size_t min_buffer_size;
60
61   bool fatal_error;
62
63   struct vn_cs_encoder_buffer *buffers;
64   uint32_t buffer_count;
65   uint32_t buffer_max;
66   size_t total_committed_size;
67
68   /* the current buffer is buffers[buffer_count - 1].shmem */
69   size_t current_buffer_size;
70
71   /* TODO remove when blob_id_0 support gets required */
72   uint32_t current_buffer_roundtrip;
73
74   /* cur is the write pointer.  When cur passes end, the slow path is
75    * triggered.
76    */
77   void *cur;
78   const void *end;
79};
80
81struct vn_cs_decoder {
82   const void *cur;
83   const void *end;
84};
85
86struct vn_cs_renderer_protocol_info {
87   simple_mtx_t mutex;
88   bool init_once;
89   uint32_t api_version;
90   BITSET_DECLARE(extension_bitset, VN_INFO_EXTENSION_MAX_NUMBER + 1);
91};
92
93extern struct vn_cs_renderer_protocol_info _vn_cs_renderer_protocol_info;
94
95static inline bool
96vn_cs_renderer_protocol_has_api_version(uint32_t api_version)
97{
98   return _vn_cs_renderer_protocol_info.api_version >= api_version;
99}
100
101static inline bool
102vn_cs_renderer_protocol_has_extension(uint32_t ext_number)
103{
104   return BITSET_TEST(_vn_cs_renderer_protocol_info.extension_bitset,
105                      ext_number);
106}
107
108void
109vn_cs_renderer_protocol_info_init(struct vn_instance *instance);
110
111void
112vn_cs_encoder_init(struct vn_cs_encoder *enc,
113                   struct vn_instance *instance,
114                   enum vn_cs_encoder_storage_type storage_type,
115                   size_t min_size);
116
117void
118vn_cs_encoder_fini(struct vn_cs_encoder *enc);
119
120void
121vn_cs_encoder_reset(struct vn_cs_encoder *enc);
122
123static inline void
124vn_cs_encoder_set_fatal(const struct vn_cs_encoder *enc)
125{
126   /* This is fatal and should be treated as VK_ERROR_DEVICE_LOST or even
127    * abort().  Note that vn_cs_encoder_reset does not clear this.
128    */
129   ((struct vn_cs_encoder *)enc)->fatal_error = true;
130}
131
132static inline bool
133vn_cs_encoder_get_fatal(const struct vn_cs_encoder *enc)
134{
135   return enc->fatal_error;
136}
137
138static inline bool
139vn_cs_encoder_is_empty(const struct vn_cs_encoder *enc)
140{
141   return !enc->buffer_count || enc->cur == enc->buffers[0].base;
142}
143
144static inline size_t
145vn_cs_encoder_get_len(const struct vn_cs_encoder *enc)
146{
147   if (unlikely(!enc->buffer_count))
148      return 0;
149
150   size_t len = enc->total_committed_size;
151   const struct vn_cs_encoder_buffer *cur_buf =
152      &enc->buffers[enc->buffer_count - 1];
153   if (!cur_buf->committed_size)
154      len += enc->cur - cur_buf->base;
155   return len;
156}
157
158bool
159vn_cs_encoder_reserve_internal(struct vn_cs_encoder *enc, size_t size);
160
161/**
162 * Reserve space for commands.
163 */
164static inline bool
165vn_cs_encoder_reserve(struct vn_cs_encoder *enc, size_t size)
166{
167   if (unlikely(size > enc->end - enc->cur)) {
168      if (!vn_cs_encoder_reserve_internal(enc, size)) {
169         vn_cs_encoder_set_fatal(enc);
170         return false;
171      }
172      assert(size <= enc->end - enc->cur);
173   }
174
175   return true;
176}
177
178static inline void
179vn_cs_encoder_write(struct vn_cs_encoder *enc,
180                    size_t size,
181                    const void *val,
182                    size_t val_size)
183{
184   assert(val_size <= size);
185   assert(size <= enc->end - enc->cur);
186
187   /* we should not rely on the compiler to optimize away memcpy... */
188   memcpy(enc->cur, val, val_size);
189   enc->cur += size;
190}
191
192void
193vn_cs_encoder_commit(struct vn_cs_encoder *enc);
194
195static inline void
196vn_cs_decoder_init(struct vn_cs_decoder *dec, const void *data, size_t size)
197{
198   *dec = VN_CS_DECODER_INITIALIZER(data, size);
199}
200
201static inline void
202vn_cs_decoder_set_fatal(const struct vn_cs_decoder *dec)
203{
204   abort();
205}
206
207static inline bool
208vn_cs_decoder_peek_internal(const struct vn_cs_decoder *dec,
209                            size_t size,
210                            void *val,
211                            size_t val_size)
212{
213   assert(val_size <= size);
214
215   if (unlikely(size > dec->end - dec->cur)) {
216      vn_cs_decoder_set_fatal(dec);
217      memset(val, 0, val_size);
218      return false;
219   }
220
221   /* we should not rely on the compiler to optimize away memcpy... */
222   memcpy(val, dec->cur, val_size);
223   return true;
224}
225
226static inline void
227vn_cs_decoder_read(struct vn_cs_decoder *dec,
228                   size_t size,
229                   void *val,
230                   size_t val_size)
231{
232   if (vn_cs_decoder_peek_internal(dec, size, val, val_size))
233      dec->cur += size;
234}
235
236static inline void
237vn_cs_decoder_peek(const struct vn_cs_decoder *dec,
238                   size_t size,
239                   void *val,
240                   size_t val_size)
241{
242   vn_cs_decoder_peek_internal(dec, size, val, val_size);
243}
244
245static inline vn_object_id
246vn_cs_handle_load_id(const void **handle, VkObjectType type)
247{
248   return *handle ? vn_object_get_id(*handle, type) : 0;
249}
250
251static inline void
252vn_cs_handle_store_id(void **handle, vn_object_id id, VkObjectType type)
253{
254   vn_object_set_id(*handle, id, type);
255}
256
257#endif /* VN_CS_H */
258