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