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
40 enum 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
49 struct vn_cs_encoder_buffer {
50 struct vn_renderer_shmem *shmem;
51 size_t offset;
52 void *base;
53 size_t committed_size;
54 };
55
56 struct 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
81 struct vn_cs_decoder {
82 const void *cur;
83 const void *end;
84 };
85
86 struct 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
93 extern struct vn_cs_renderer_protocol_info _vn_cs_renderer_protocol_info;
94
95 static inline bool
vn_cs_renderer_protocol_has_api_version(uint32_t api_version)96 vn_cs_renderer_protocol_has_api_version(uint32_t api_version)
97 {
98 return _vn_cs_renderer_protocol_info.api_version >= api_version;
99 }
100
101 static inline bool
vn_cs_renderer_protocol_has_extension(uint32_t ext_number)102 vn_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
108 void
109 vn_cs_renderer_protocol_info_init(struct vn_instance *instance);
110
111 void
112 vn_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
117 void
118 vn_cs_encoder_fini(struct vn_cs_encoder *enc);
119
120 void
121 vn_cs_encoder_reset(struct vn_cs_encoder *enc);
122
123 static inline void
vn_cs_encoder_set_fatal(const struct vn_cs_encoder * enc)124 vn_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
132 static inline bool
vn_cs_encoder_get_fatal(const struct vn_cs_encoder * enc)133 vn_cs_encoder_get_fatal(const struct vn_cs_encoder *enc)
134 {
135 return enc->fatal_error;
136 }
137
138 static inline bool
vn_cs_encoder_is_empty(const struct vn_cs_encoder * enc)139 vn_cs_encoder_is_empty(const struct vn_cs_encoder *enc)
140 {
141 return !enc->buffer_count || enc->cur == enc->buffers[0].base;
142 }
143
144 static inline size_t
vn_cs_encoder_get_len(const struct vn_cs_encoder * enc)145 vn_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
158 bool
159 vn_cs_encoder_reserve_internal(struct vn_cs_encoder *enc, size_t size);
160
161 /**
162 * Reserve space for commands.
163 */
164 static inline bool
vn_cs_encoder_reserve(struct vn_cs_encoder * enc,size_t size)165 vn_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
178 static inline void
vn_cs_encoder_write(struct vn_cs_encoder * enc,size_t size,const void * val,size_t val_size)179 vn_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
192 void
193 vn_cs_encoder_commit(struct vn_cs_encoder *enc);
194
195 static inline void
vn_cs_decoder_init(struct vn_cs_decoder * dec,const void * data,size_t size)196 vn_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
201 static inline void
vn_cs_decoder_set_fatal(const struct vn_cs_decoder * dec)202 vn_cs_decoder_set_fatal(const struct vn_cs_decoder *dec)
203 {
204 abort();
205 }
206
207 static inline bool
vn_cs_decoder_peek_internal(const struct vn_cs_decoder * dec,size_t size,void * val,size_t val_size)208 vn_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
226 static inline void
vn_cs_decoder_read(struct vn_cs_decoder * dec,size_t size,void * val,size_t val_size)227 vn_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
236 static inline void
vn_cs_decoder_peek(const struct vn_cs_decoder * dec,size_t size,void * val,size_t val_size)237 vn_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
245 static inline vn_object_id
vn_cs_handle_load_id(const void ** handle,VkObjectType type)246 vn_cs_handle_load_id(const void **handle, VkObjectType type)
247 {
248 return *handle ? vn_object_get_id(*handle, type) : 0;
249 }
250
251 static inline void
vn_cs_handle_store_id(void ** handle,vn_object_id id,VkObjectType type)252 vn_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