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
37 struct vn_cs_encoder_buffer {
38 struct vn_renderer_shmem *shmem;
39 size_t offset;
40 void *base;
41 size_t committed_size;
42 };
43
44 struct 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
67 struct vn_cs_decoder {
68 const void *cur;
69 const void *end;
70 };
71
72 void
73 vn_cs_encoder_init_indirect(struct vn_cs_encoder *enc,
74 struct vn_instance *instance,
75 size_t min_size);
76
77 void
78 vn_cs_encoder_fini(struct vn_cs_encoder *enc);
79
80 void
81 vn_cs_encoder_reset(struct vn_cs_encoder *enc);
82
83 static inline void
vn_cs_encoder_set_fatal(const struct vn_cs_encoder * enc)84 vn_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
92 static inline bool
vn_cs_encoder_get_fatal(const struct vn_cs_encoder * enc)93 vn_cs_encoder_get_fatal(const struct vn_cs_encoder *enc)
94 {
95 return enc->fatal_error;
96 }
97
98 static inline bool
vn_cs_encoder_is_empty(const struct vn_cs_encoder * enc)99 vn_cs_encoder_is_empty(const struct vn_cs_encoder *enc)
100 {
101 return !enc->buffer_count || enc->cur == enc->buffers[0].base;
102 }
103
104 static inline size_t
vn_cs_encoder_get_len(const struct vn_cs_encoder * enc)105 vn_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
118 bool
119 vn_cs_encoder_reserve_internal(struct vn_cs_encoder *enc, size_t size);
120
121 /**
122 * Reserve space for commands.
123 */
124 static inline bool
vn_cs_encoder_reserve(struct vn_cs_encoder * enc,size_t size)125 vn_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
138 static inline void
vn_cs_encoder_write(struct vn_cs_encoder * enc,size_t size,const void * val,size_t val_size)139 vn_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
152 void
153 vn_cs_encoder_commit(struct vn_cs_encoder *enc);
154
155 static inline void
vn_cs_decoder_init(struct vn_cs_decoder * dec,const void * data,size_t size)156 vn_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
161 static inline void
vn_cs_decoder_set_fatal(const struct vn_cs_decoder * dec)162 vn_cs_decoder_set_fatal(const struct vn_cs_decoder *dec)
163 {
164 abort();
165 }
166
167 static inline bool
vn_cs_decoder_peek_internal(const struct vn_cs_decoder * dec,size_t size,void * val,size_t val_size)168 vn_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
186 static inline void
vn_cs_decoder_read(struct vn_cs_decoder * dec,size_t size,void * val,size_t val_size)187 vn_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
196 static inline void
vn_cs_decoder_peek(const struct vn_cs_decoder * dec,size_t size,void * val,size_t val_size)197 vn_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
205 static inline vn_object_id
vn_cs_handle_load_id(const void ** handle,VkObjectType type)206 vn_cs_handle_load_id(const void **handle, VkObjectType type)
207 {
208 return *handle ? vn_object_get_id(*handle, type) : 0;
209 }
210
211 static inline void
vn_cs_handle_store_id(void ** handle,vn_object_id id,VkObjectType type)212 vn_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