| /* |
| * Copyright 2019 Google LLC |
| * SPDX-License-Identifier: MIT |
| */ |
| |
| #ifndef VN_CS_H |
| #define VN_CS_H |
| |
| #include "vn_common.h" |
| |
| #include "venus-protocol/vn_protocol_driver_info.h" |
| |
| #define VN_CS_ENCODER_BUFFER_INITIALIZER(storage) \ |
| (struct vn_cs_encoder_buffer) \ |
| { \ |
| .base = storage, \ |
| } |
| |
| /* note that buffers points to an unamed local variable */ |
| #define VN_CS_ENCODER_INITIALIZER_LOCAL(storage, size) \ |
| (struct vn_cs_encoder) \ |
| { \ |
| .storage_type = VN_CS_ENCODER_STORAGE_POINTER, \ |
| .buffers = &VN_CS_ENCODER_BUFFER_INITIALIZER(storage), \ |
| .buffer_count = 1, .buffer_max = 1, .current_buffer_size = size, \ |
| .cur = storage, .end = (const void *)(storage) + (size), \ |
| } |
| |
| #define VN_CS_ENCODER_INITIALIZER(buf, size) \ |
| (struct vn_cs_encoder) \ |
| { \ |
| .storage_type = VN_CS_ENCODER_STORAGE_POINTER, .buffers = (buf), \ |
| .buffer_count = 1, .buffer_max = 1, .current_buffer_size = size, \ |
| .cur = (buf)->base, .end = (buf)->base + (size), \ |
| } |
| |
| #define VN_CS_DECODER_INITIALIZER(storage, size) \ |
| (struct vn_cs_decoder) \ |
| { \ |
| .cur = storage, .end = (const void *)(storage) + (size), \ |
| } |
| |
| enum vn_cs_encoder_storage_type { |
| /* a pointer to an externally-managed storage */ |
| VN_CS_ENCODER_STORAGE_POINTER, |
| /* an array of dynamically allocated shmems */ |
| VN_CS_ENCODER_STORAGE_SHMEM_ARRAY, |
| /* same as above, but shmems are suballocated from a pool */ |
| VN_CS_ENCODER_STORAGE_SHMEM_POOL, |
| }; |
| |
| struct vn_cs_encoder_buffer { |
| struct vn_renderer_shmem *shmem; |
| size_t offset; |
| void *base; |
| size_t committed_size; |
| }; |
| |
| struct vn_cs_encoder { |
| struct vn_instance *instance; /* TODO shmem cache */ |
| enum vn_cs_encoder_storage_type storage_type; |
| size_t min_buffer_size; |
| |
| bool fatal_error; |
| |
| struct vn_cs_encoder_buffer *buffers; |
| uint32_t buffer_count; |
| uint32_t buffer_max; |
| size_t total_committed_size; |
| |
| /* the current buffer is buffers[buffer_count - 1].shmem */ |
| size_t current_buffer_size; |
| |
| /* TODO remove when blob_id_0 support gets required */ |
| uint32_t current_buffer_roundtrip; |
| |
| /* cur is the write pointer. When cur passes end, the slow path is |
| * triggered. |
| */ |
| void *cur; |
| const void *end; |
| }; |
| |
| struct vn_cs_decoder { |
| const void *cur; |
| const void *end; |
| }; |
| |
| struct vn_cs_renderer_protocol_info { |
| simple_mtx_t mutex; |
| bool init_once; |
| uint32_t api_version; |
| BITSET_DECLARE(extension_bitset, VN_INFO_EXTENSION_MAX_NUMBER + 1); |
| }; |
| |
| extern struct vn_cs_renderer_protocol_info _vn_cs_renderer_protocol_info; |
| |
| static inline bool |
| vn_cs_renderer_protocol_has_api_version(uint32_t api_version) |
| { |
| return _vn_cs_renderer_protocol_info.api_version >= api_version; |
| } |
| |
| static inline bool |
| vn_cs_renderer_protocol_has_extension(uint32_t ext_number) |
| { |
| return BITSET_TEST(_vn_cs_renderer_protocol_info.extension_bitset, |
| ext_number); |
| } |
| |
| void |
| vn_cs_renderer_protocol_info_init(struct vn_instance *instance); |
| |
| void |
| vn_cs_encoder_init(struct vn_cs_encoder *enc, |
| struct vn_instance *instance, |
| enum vn_cs_encoder_storage_type storage_type, |
| size_t min_size); |
| |
| void |
| vn_cs_encoder_fini(struct vn_cs_encoder *enc); |
| |
| void |
| vn_cs_encoder_reset(struct vn_cs_encoder *enc); |
| |
| static inline void |
| vn_cs_encoder_set_fatal(const struct vn_cs_encoder *enc) |
| { |
| /* This is fatal and should be treated as VK_ERROR_DEVICE_LOST or even |
| * abort(). Note that vn_cs_encoder_reset does not clear this. |
| */ |
| ((struct vn_cs_encoder *)enc)->fatal_error = true; |
| } |
| |
| static inline bool |
| vn_cs_encoder_get_fatal(const struct vn_cs_encoder *enc) |
| { |
| return enc->fatal_error; |
| } |
| |
| static inline bool |
| vn_cs_encoder_is_empty(const struct vn_cs_encoder *enc) |
| { |
| return !enc->buffer_count || enc->cur == enc->buffers[0].base; |
| } |
| |
| static inline size_t |
| vn_cs_encoder_get_len(const struct vn_cs_encoder *enc) |
| { |
| if (unlikely(!enc->buffer_count)) |
| return 0; |
| |
| size_t len = enc->total_committed_size; |
| const struct vn_cs_encoder_buffer *cur_buf = |
| &enc->buffers[enc->buffer_count - 1]; |
| if (!cur_buf->committed_size) |
| len += enc->cur - cur_buf->base; |
| return len; |
| } |
| |
| bool |
| vn_cs_encoder_reserve_internal(struct vn_cs_encoder *enc, size_t size); |
| |
| /** |
| * Reserve space for commands. |
| */ |
| static inline bool |
| vn_cs_encoder_reserve(struct vn_cs_encoder *enc, size_t size) |
| { |
| if (unlikely(size > enc->end - enc->cur)) { |
| if (!vn_cs_encoder_reserve_internal(enc, size)) { |
| vn_cs_encoder_set_fatal(enc); |
| return false; |
| } |
| assert(size <= enc->end - enc->cur); |
| } |
| |
| return true; |
| } |
| |
| static inline void |
| vn_cs_encoder_write(struct vn_cs_encoder *enc, |
| size_t size, |
| const void *val, |
| size_t val_size) |
| { |
| assert(val_size <= size); |
| assert(size <= enc->end - enc->cur); |
| |
| /* we should not rely on the compiler to optimize away memcpy... */ |
| memcpy(enc->cur, val, val_size); |
| enc->cur += size; |
| } |
| |
| void |
| vn_cs_encoder_commit(struct vn_cs_encoder *enc); |
| |
| static inline void |
| vn_cs_decoder_init(struct vn_cs_decoder *dec, const void *data, size_t size) |
| { |
| *dec = VN_CS_DECODER_INITIALIZER(data, size); |
| } |
| |
| static inline void |
| vn_cs_decoder_set_fatal(const struct vn_cs_decoder *dec) |
| { |
| abort(); |
| } |
| |
| static inline bool |
| vn_cs_decoder_peek_internal(const struct vn_cs_decoder *dec, |
| size_t size, |
| void *val, |
| size_t val_size) |
| { |
| assert(val_size <= size); |
| |
| if (unlikely(size > dec->end - dec->cur)) { |
| vn_cs_decoder_set_fatal(dec); |
| memset(val, 0, val_size); |
| return false; |
| } |
| |
| /* we should not rely on the compiler to optimize away memcpy... */ |
| memcpy(val, dec->cur, val_size); |
| return true; |
| } |
| |
| static inline void |
| vn_cs_decoder_read(struct vn_cs_decoder *dec, |
| size_t size, |
| void *val, |
| size_t val_size) |
| { |
| if (vn_cs_decoder_peek_internal(dec, size, val, val_size)) |
| dec->cur += size; |
| } |
| |
| static inline void |
| vn_cs_decoder_peek(const struct vn_cs_decoder *dec, |
| size_t size, |
| void *val, |
| size_t val_size) |
| { |
| vn_cs_decoder_peek_internal(dec, size, val, val_size); |
| } |
| |
| static inline vn_object_id |
| vn_cs_handle_load_id(const void **handle, VkObjectType type) |
| { |
| return *handle ? vn_object_get_id(*handle, type) : 0; |
| } |
| |
| static inline void |
| vn_cs_handle_store_id(void **handle, vn_object_id id, VkObjectType type) |
| { |
| vn_object_set_id(*handle, id, type); |
| } |
| |
| #endif /* VN_CS_H */ |