ilo: use ilo_builder for kernels and STATE_BASE_ADDRESS
[mesa.git] / src / gallium / drivers / ilo / ilo_cp.h
1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 2012-2013 LunarG, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Chia-I Wu <olv@lunarg.com>
26 */
27
28 #ifndef ILO_CP_H
29 #define ILO_CP_H
30
31 #include "intel_winsys.h"
32
33 #include "ilo_builder.h"
34 #include "ilo_common.h"
35
36 struct ilo_cp;
37 struct ilo_shader_cache;
38
39 typedef void (*ilo_cp_callback)(struct ilo_cp *cp, void *data);
40
41 struct ilo_cp_owner {
42 ilo_cp_callback release_callback;
43 void *release_data;
44 };
45
46 /**
47 * Command parser.
48 */
49 struct ilo_cp {
50 struct intel_winsys *winsys;
51 struct ilo_shader_cache *shader_cache;
52 struct intel_context *render_ctx;
53
54 ilo_cp_callback flush_callback;
55 void *flush_callback_data;
56
57 const struct ilo_cp_owner *owner;
58 int owner_reserve;
59
60 enum intel_ring_type ring;
61 bool no_implicit_flush;
62 unsigned one_off_flags;
63
64 struct ilo_builder builder;
65 struct intel_bo *last_submitted_bo;
66
67 unsigned pos;
68 uint32_t *ptr;
69 int cmd_cur, cmd_end;
70 };
71
72 struct ilo_cp *
73 ilo_cp_create(const struct ilo_dev_info *dev,
74 struct intel_winsys *winsys,
75 struct ilo_shader_cache *shc);
76
77 void
78 ilo_cp_destroy(struct ilo_cp *cp);
79
80 void
81 ilo_cp_flush_internal(struct ilo_cp *cp);
82
83 static inline void
84 ilo_cp_flush(struct ilo_cp *cp, const char *reason)
85 {
86 if (ilo_debug & ILO_DEBUG_FLUSH) {
87 ilo_printf("cp flushed for %s because of %s: ",
88 (cp->ring == INTEL_RING_RENDER) ? "render" : "other", reason);
89 ilo_builder_batch_print_stats(&cp->builder);
90 }
91
92 ilo_cp_flush_internal(cp);
93 }
94
95 /**
96 * Return true if the parser buffer is empty.
97 */
98 static inline bool
99 ilo_cp_empty(struct ilo_cp *cp)
100 {
101 return !ilo_builder_batch_used(&cp->builder);
102 }
103
104 /**
105 * Return the remaining space (in dwords) in the parser buffer.
106 */
107 static inline int
108 ilo_cp_space(struct ilo_cp *cp)
109 {
110 const int space = ilo_builder_batch_space(&cp->builder);
111 const int mi_batch_buffer_end_space = 2;
112
113 assert(space >= cp->owner_reserve + mi_batch_buffer_end_space);
114
115 return space - cp->owner_reserve - mi_batch_buffer_end_space;
116 }
117
118 /**
119 * Internal function called by functions that flush implicitly.
120 */
121 static inline void
122 ilo_cp_implicit_flush(struct ilo_cp *cp)
123 {
124 if (cp->no_implicit_flush) {
125 assert(!"unexpected command parser flush");
126 ilo_builder_batch_discard(&cp->builder);
127 }
128
129 ilo_cp_flush(cp, "out of space (implicit)");
130 }
131
132 /**
133 * Set the ring buffer.
134 */
135 static inline void
136 ilo_cp_set_ring(struct ilo_cp *cp, enum intel_ring_type ring)
137 {
138 if (cp->ring != ring) {
139 ilo_cp_implicit_flush(cp);
140 cp->ring = ring;
141 }
142 }
143
144 /**
145 * Assert that no function should flush implicitly.
146 */
147 static inline void
148 ilo_cp_assert_no_implicit_flush(struct ilo_cp *cp, bool enable)
149 {
150 cp->no_implicit_flush = enable;
151 }
152
153 /**
154 * Set one-off flags. They will be cleared after flushing.
155 */
156 static inline void
157 ilo_cp_set_one_off_flags(struct ilo_cp *cp, unsigned flags)
158 {
159 cp->one_off_flags |= flags;
160 }
161
162 /**
163 * Set flush callback. The callback is invoked after the bo has been
164 * successfully executed, and before the bo is reallocated.
165 */
166 static inline void
167 ilo_cp_set_flush_callback(struct ilo_cp *cp, ilo_cp_callback callback,
168 void *data)
169 {
170 cp->flush_callback = callback;
171 cp->flush_callback_data = data;
172 }
173
174 /**
175 * Set the parser owner. If this is a new owner, the previous owner is
176 * notified and the space it reserved is reclaimed.
177 *
178 * \return true if this is a new owner
179 */
180 static inline bool
181 ilo_cp_set_owner(struct ilo_cp *cp, const struct ilo_cp_owner *owner,
182 int reserve)
183 {
184 const bool new_owner = (cp->owner != owner);
185
186 /* release current owner */
187 if (new_owner && cp->owner) {
188 const bool no_implicit_flush = cp->no_implicit_flush;
189
190 /* reclaim the reserved space */
191 cp->owner_reserve = 0;
192
193 /* invoke the release callback */
194 cp->no_implicit_flush = true;
195 cp->owner->release_callback(cp, cp->owner->release_data);
196 cp->no_implicit_flush = no_implicit_flush;
197
198 cp->owner = NULL;
199 }
200
201 if (cp->owner_reserve != reserve) {
202 const int extra = reserve - cp->owner_reserve;
203
204 if (ilo_cp_space(cp) < extra) {
205 ilo_cp_implicit_flush(cp);
206
207 assert(ilo_cp_space(cp) >= reserve);
208 cp->owner_reserve = reserve;
209 }
210 else {
211 cp->owner_reserve += extra;
212 }
213 }
214
215 /* set owner last because of the possible flush above */
216 cp->owner = owner;
217
218 return new_owner;
219 }
220
221 /**
222 * Begin writing a command.
223 */
224 static inline void
225 ilo_cp_begin(struct ilo_cp *cp, int cmd_size)
226 {
227 if (ilo_cp_space(cp) < cmd_size) {
228 ilo_cp_implicit_flush(cp);
229 assert(ilo_cp_space(cp) >= cmd_size);
230 }
231
232 cp->pos = ilo_builder_batch_pointer(&cp->builder, cmd_size, &cp->ptr);
233
234 cp->cmd_cur = 0;
235 cp->cmd_end = cmd_size;
236 }
237
238 /**
239 * Begin writing data to a space stolen from the top of the parser buffer.
240 *
241 * \param item builder item type
242 * \param data_size in dwords
243 * \param align in dwords
244 * \param bo_offset in bytes to the stolen space
245 */
246 static inline void
247 ilo_cp_steal(struct ilo_cp *cp, enum ilo_builder_item_type item,
248 int data_size, int align, uint32_t *bo_offset)
249 {
250 if (!align)
251 align = 1;
252
253 /* flush if there is not enough space after stealing */
254 if (ilo_cp_space(cp) < data_size + align - 1) {
255 ilo_cp_implicit_flush(cp);
256 assert(ilo_cp_space(cp) >= data_size + align - 1);
257 }
258
259 cp->pos = ilo_builder_state_pointer(&cp->builder,
260 item, align << 2, data_size, &cp->ptr) >> 2;
261
262 cp->cmd_cur = 0;
263 cp->cmd_end = data_size;
264
265 /* offset in cp->bo */
266 if (bo_offset)
267 *bo_offset = cp->pos << 2;
268 }
269
270 /**
271 * Write a dword to the parser buffer. This function must be enclosed by
272 * ilo_cp_begin()/ilo_cp_steal() and ilo_cp_end().
273 */
274 static inline void
275 ilo_cp_write(struct ilo_cp *cp, uint32_t val)
276 {
277 assert(cp->cmd_cur < cp->cmd_end);
278 cp->ptr[cp->cmd_cur++] = val;
279 }
280
281 /**
282 * Write multiple dwords to the parser buffer.
283 */
284 static inline void
285 ilo_cp_write_multi(struct ilo_cp *cp, const void *vals, int num_vals)
286 {
287 assert(cp->cmd_cur + num_vals <= cp->cmd_end);
288 memcpy(cp->ptr + cp->cmd_cur, vals, num_vals * 4);
289 cp->cmd_cur += num_vals;
290 }
291
292 /**
293 * Write a bo to the parser buffer. In addition to writing the offset of the
294 * bo to the buffer, it also emits a relocation.
295 */
296 static inline void
297 ilo_cp_write_bo(struct ilo_cp *cp, uint32_t val,
298 struct intel_bo *bo, uint32_t flags)
299 {
300 if (bo) {
301 ilo_builder_batch_reloc(&cp->builder, cp->pos + cp->cmd_cur,
302 bo, val, flags);
303 cp->cmd_cur++;
304 }
305 else {
306 ilo_cp_write(cp, 0);
307 }
308 }
309
310 /**
311 * End a command. Every ilo_cp_begin() or ilo_cp_steal() must have a
312 * matching ilo_cp_end().
313 */
314 static inline void
315 ilo_cp_end(struct ilo_cp *cp)
316 {
317 assert(cp->cmd_cur == cp->cmd_end);
318 }
319
320 /**
321 * A variant of ilo_cp_steal() where the data are written via the returned
322 * pointer.
323 *
324 * \return ptr pointer where the data are written to. It is valid until any
325 * change is made to the parser.
326 */
327 static inline void *
328 ilo_cp_steal_ptr(struct ilo_cp *cp, enum ilo_builder_item_type item,
329 int data_size, int align, uint32_t *bo_offset)
330 {
331 void *ptr;
332
333 ilo_cp_steal(cp, item, data_size, align, bo_offset);
334
335 ptr = &cp->ptr[cp->cmd_cur];
336 cp->cmd_cur = cp->cmd_end;
337
338 ilo_cp_end(cp);
339
340 return ptr;
341 }
342
343 #endif /* ILO_CP_H */