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