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