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#define VN_CS_ENCODER_BUFFER_INITIALIZER(storage) \ 12 (struct vn_cs_encoder_buffer) { .base = storage, } 13 14/* note that buffers points to an unamed local variable */ 15#define VN_CS_ENCODER_INITIALIZER_LOCAL(storage, size) \ 16 (struct vn_cs_encoder) \ 17 { \ 18 .buffers = &VN_CS_ENCODER_BUFFER_INITIALIZER(storage), \ 19 .buffer_count = 1, .buffer_max = 1, .current_buffer_size = size, \ 20 .cur = storage, .end = (const void *)(storage) + (size), \ 21 } 22 23#define VN_CS_ENCODER_INITIALIZER(buf, size) \ 24 (struct vn_cs_encoder) \ 25 { \ 26 .buffers = (buf), .buffer_count = 1, .buffer_max = 1, \ 27 .current_buffer_size = size, .cur = (buf)->base, \ 28 .end = (buf)->base + (size), \ 29 } 30 31#define VN_CS_DECODER_INITIALIZER(storage, size) \ 32 (struct vn_cs_decoder) \ 33 { \ 34 .cur = storage, .end = (const void *)(storage) + (size), \ 35 } 36 37struct vn_cs_encoder_buffer { 38 struct vn_renderer_shmem *shmem; 39 size_t offset; 40 void *base; 41 size_t committed_size; 42}; 43 44struct vn_cs_encoder { 45 struct vn_instance *instance; /* TODO shmem cache */ 46 size_t min_buffer_size; 47 bool indirect; 48 49 bool fatal_error; 50 51 struct vn_cs_encoder_buffer *buffers; 52 uint32_t buffer_count; 53 uint32_t buffer_max; 54 size_t total_committed_size; 55 56 /* the current buffer is buffers[buffer_count - 1].shmem */ 57 size_t current_buffer_size; 58 uint32_t current_buffer_roundtrip; 59 60 /* cur is the write pointer. When cur passes end, the slow path is 61 * triggered. 62 */ 63 void *cur; 64 const void *end; 65}; 66 67struct vn_cs_decoder { 68 const void *cur; 69 const void *end; 70}; 71 72void 73vn_cs_encoder_init_indirect(struct vn_cs_encoder *enc, 74 struct vn_instance *instance, 75 size_t min_size); 76 77void 78vn_cs_encoder_fini(struct vn_cs_encoder *enc); 79 80void 81vn_cs_encoder_reset(struct vn_cs_encoder *enc); 82 83static inline void 84vn_cs_encoder_set_fatal(const struct vn_cs_encoder *enc) 85{ 86 /* This is fatal and should be treated as VK_ERROR_DEVICE_LOST or even 87 * abort(). Note that vn_cs_encoder_reset does not clear this. 88 */ 89 ((struct vn_cs_encoder *)enc)->fatal_error = true; 90} 91 92static inline bool 93vn_cs_encoder_get_fatal(const struct vn_cs_encoder *enc) 94{ 95 return enc->fatal_error; 96} 97 98static inline bool 99vn_cs_encoder_is_empty(const struct vn_cs_encoder *enc) 100{ 101 return !enc->buffer_count || enc->cur == enc->buffers[0].base; 102} 103 104static inline size_t 105vn_cs_encoder_get_len(const struct vn_cs_encoder *enc) 106{ 107 if (unlikely(!enc->buffer_count)) 108 return 0; 109 110 size_t len = enc->total_committed_size; 111 const struct vn_cs_encoder_buffer *cur_buf = 112 &enc->buffers[enc->buffer_count - 1]; 113 if (!cur_buf->committed_size) 114 len += enc->cur - cur_buf->base; 115 return len; 116} 117 118bool 119vn_cs_encoder_reserve_internal(struct vn_cs_encoder *enc, size_t size); 120 121/** 122 * Reserve space for commands. 123 */ 124static inline bool 125vn_cs_encoder_reserve(struct vn_cs_encoder *enc, size_t size) 126{ 127 if (unlikely(size > enc->end - enc->cur)) { 128 if (!vn_cs_encoder_reserve_internal(enc, size)) { 129 vn_cs_encoder_set_fatal(enc); 130 return false; 131 } 132 assert(size <= enc->end - enc->cur); 133 } 134 135 return true; 136} 137 138static inline void 139vn_cs_encoder_write(struct vn_cs_encoder *enc, 140 size_t size, 141 const void *val, 142 size_t val_size) 143{ 144 assert(val_size <= size); 145 assert(size <= enc->end - enc->cur); 146 147 /* we should not rely on the compiler to optimize away memcpy... */ 148 memcpy(enc->cur, val, val_size); 149 enc->cur += size; 150} 151 152void 153vn_cs_encoder_commit(struct vn_cs_encoder *enc); 154 155static inline void 156vn_cs_decoder_init(struct vn_cs_decoder *dec, const void *data, size_t size) 157{ 158 *dec = VN_CS_DECODER_INITIALIZER(data, size); 159} 160 161static inline void 162vn_cs_decoder_set_fatal(const struct vn_cs_decoder *dec) 163{ 164 abort(); 165} 166 167static inline bool 168vn_cs_decoder_peek_internal(const struct vn_cs_decoder *dec, 169 size_t size, 170 void *val, 171 size_t val_size) 172{ 173 assert(val_size <= size); 174 175 if (unlikely(size > dec->end - dec->cur)) { 176 vn_cs_decoder_set_fatal(dec); 177 memset(val, 0, val_size); 178 return false; 179 } 180 181 /* we should not rely on the compiler to optimize away memcpy... */ 182 memcpy(val, dec->cur, val_size); 183 return true; 184} 185 186static inline void 187vn_cs_decoder_read(struct vn_cs_decoder *dec, 188 size_t size, 189 void *val, 190 size_t val_size) 191{ 192 if (vn_cs_decoder_peek_internal(dec, size, val, val_size)) 193 dec->cur += size; 194} 195 196static inline void 197vn_cs_decoder_peek(const struct vn_cs_decoder *dec, 198 size_t size, 199 void *val, 200 size_t val_size) 201{ 202 vn_cs_decoder_peek_internal(dec, size, val, val_size); 203} 204 205static inline vn_object_id 206vn_cs_handle_load_id(const void **handle, VkObjectType type) 207{ 208 return *handle ? vn_object_get_id(*handle, type) : 0; 209} 210 211static inline void 212vn_cs_handle_store_id(void **handle, vn_object_id id, VkObjectType type) 213{ 214 vn_object_set_id(*handle, id, type); 215} 216 217#endif /* VN_CS_H */ 218